Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

Python Standard Library

The batteries-included modules that mean you rarely need a dependency — collections, itertools, functools, pathlib, and more.

The standard library ships with every Python install, so each module here is a dependency you never add, pin or audit. The rows assume Python 3.10 or newer and flag anything later, such as tomllib (3.11) and itertools.batched (3.12).

Two habits make it pay off. Reach for the purpose-built structure instead of a hand-rolled one: Counter rather than a dict of counts, deque rather than list.pop(0). And know the complexity each one buys you, because that is usually why it exists.

collections

defaultdict
d = defaultdict(list); d[k].append(x) — no KeyError; even reading d[k] inserts it
Counter
Counter(words).most_common(3) — frequency counting
c1 + c2 · c1 - c2
add or subtract Counters; the result drops zero and negative counts
deque
deque(maxlen=n) — O(1) appends/pops both ends; BFS queues
namedtuple
Point = namedtuple("Point", "x y") — lightweight records
OrderedDict
move_to_end(k) and popitem(last=False) are O(1) — an LRU in a few lines
ChainMap
layered lookups without copying: ChainMap(cli_args, env, defaults)

itertools

product · combinations
product(a, b) · combinations(xs, 2) · permutations(xs)
chain · groupby
chain(*lists) flattens one level; groupby groups only ADJACENT items — sort by the key first
accumulate · pairwise
accumulate(xs) running totals; pairwise(xs) sliding pairs (3.10+)
islice(it, 10)
first 10 items of any iterator, even an infinite one like count()
batched(xs, 100)
chunks of up to 100 as tuples (3.12+) — batch your API calls
zip_longest(a, b)
zip to the longest input, padding with fillvalue; plain zip stops at the shortest

functools & operator

@lru_cache(maxsize=None)
cache results per argument tuple; @cache (3.9+) is the same, shorter
reduce
reduce(operator.mul, xs, 1) folds a sequence; math.prod(xs) is clearer here
partial(f, x=1)
pre-fill arguments to make a new callable — handy for callbacks and map
@wraps(func)
inside a decorator, keep the wrapped function’s name and docstring
@cached_property
compute a property once per instance, then store it as a plain attribute
itemgetter · attrgetter
fast sort keys: key=itemgetter("age") in sorted or max

Files, paths & formats

pathlib
Path("a/b.txt").read_text() · .glob("*.py") · .exists()
p.rglob("*.py")
recursive glob; p.stem, p.suffix, p.with_suffix(".bak") for names
mkdir(parents=True)
create a directory and its parents; add exist_ok=True so reruns don’t fail
json
json.loads(s) · json.dumps(obj, indent=2)
json.dump(obj, f)
write to a file (json.load(f) reads); default=str serializes dates
csv.DictReader(f)
rows as dicts keyed by the header; open the file with newline=""
tomllib.load(f)
read TOML such as pyproject.toml (3.11+); open the file in binary mode
shutil
copytree, rmtree, move, which("git") — file operations os lacks
tempfile
TemporaryDirectory() in a with block — removed when the block exits

Dates & time

datetime
aware UTC now: datetime.now(timezone.utc); utcnow() is naive and deprecated (3.12)
fromisoformat(s)
parse ISO 8601 strings; accepts most variants, including a trailing Z, from 3.11
zoneinfo
ZoneInfo("Europe/Berlin") — real time zones with DST, no pytz (3.9+)
timedelta
now + timedelta(days=7); subtracting datetimes gives one, .total_seconds() to compare
time.perf_counter()
monotonic high-resolution clock for timing; time.time() jumps when the clock is adjusted

Data & algorithms

heapq
heappush/heappop — a min-heap; nlargest(k, xs)
heappush(h, (-p, x))
max-heap by negating priorities; tuples compare element by element
bisect
bisect_left(sorted_list, x) — binary search insert point
dataclasses
@dataclass — auto __init__/__repr__/__eq__
@dataclass(frozen=True)
immutable and hashable; slots=True (3.10+) saves memory per instance
enum
class Color(Enum): RED = 1 — named constants; StrEnum (3.11+) for strings
statistics
mean, median, stdev, quantiles(xs, n=100) for percentiles
math
isclose for floats, comb(n, k), prod, isqrt, inf
random
choice, sample(xs, k), shuffle; use secrets for anything security-related
decimal.Decimal
exact decimal arithmetic for money; build from strings: Decimal("0.10")
graphlib
TopologicalSorter(deps) then .static_order() — dependency order; raises on cycles
enumerate / zip
for i, x in enumerate(xs) · zip(a, b, strict=True)

Concurrency & processes

subprocess.run
pass a list, plus check=True, capture_output=True, text=True — no shell injection
ThreadPoolExecutor
parallel I/O: pool.map(fetch, urls); ProcessPoolExecutor for CPU-bound work
asyncio.run(main())
start an event loop; inside, await asyncio.gather(*tasks) runs coroutines concurrently
asyncio.TaskGroup
structured concurrency: if one task fails, the others are canceled (3.11+)
asyncio.timeout(5)
async with asyncio.timeout(5): — cancels the block after 5 s (3.11+)

Text & utilities

re
re.findall, re.sub, named groups (?P<name>…); compile hot patterns once
f"{x=}"
debug print showing x=42; f"{n:,}" adds thousands separators, {v:.2f} rounds
shlex.split · quote
split a command line the way a shell does · quote a value safely for one
secrets.token_urlsafe()
random tokens for reset links and API keys — never random for these
hashlib.sha256(b)
.hexdigest() for checksums; never for passwords — use a slow KDF like scrypt
logging.basicConfig
level=logging.INFO plus a format; call it once at startup
argparse
CLI flags with help: p.add_argument("--n", type=int)

From the command line

python -m http.server
serve the current directory on port 8000 — quick file sharing
python -m venv .venv
project-local environment; activate with source .venv/bin/activate
python -m timeit
micro-benchmark one statement, e.g. "sum(range(1000))"
python -m cProfile
profile a script; -s cumtime sorts by cumulative time
breakpoint()
drop into the debugger at that line; PYTHONBREAKPOINT=0 disables it

Recipes

Count the words in a file and print the top 10

from collections import Counter
from pathlib import Path
import re

words = re.findall(r"[a-z']+", Path("book.txt").read_text().lower())
for word, n in Counter(words).most_common(10):
    print(f"{n:>6}  {word}")

most_common does the sorting, and {n:>6} right-aligns the counts in a 6-character column.

Run a shell command safely and capture its output

import subprocess

result = subprocess.run(
    ["git", "log", "--oneline", "-5"],
    capture_output=True, text=True, check=True, timeout=30,
)
print(result.stdout)

A list of arguments avoids shell injection, check=True raises CalledProcessError on a non-zero exit, and timeout stops a hung child.

Fetch many URLs concurrently with threads

from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.request import urlopen

def fetch(url):
    with urlopen(url, timeout=10) as r:
        return url, r.status, len(r.read())

urls = ["https://example.com", "https://www.python.org"]
with ThreadPoolExecutor(max_workers=8) as pool:
    futures = [pool.submit(fetch, u) for u in urls]
    for f in as_completed(futures):
        print(f.result())

Threads suit I/O-bound work because the GIL is released while waiting on the network; use ProcessPoolExecutor for CPU-bound work. f.result() re-raises any exception from the worker.

An LRU cache in a few lines

from collections import OrderedDict

class LRU:
    def __init__(self, capacity):
        self.capacity, self.data = capacity, OrderedDict()

    def get(self, key):
        if key not in self.data:
            return None
        self.data.move_to_end(key)
        return self.data[key]

    def put(self, key, value):
        self.data[key] = value
        self.data.move_to_end(key)
        if len(self.data) > self.capacity:
            self.data.popitem(last=False)

move_to_end and popitem(last=False) are both O(1), which is the whole trick. To cache a function’s results, @lru_cache already does this.

Run tasks in dependency order

from graphlib import TopologicalSorter

deps = {"deploy": {"test", "build"}, "test": {"build"}, "build": {"fetch"}}
print(list(TopologicalSorter(deps).static_order()))
# ['fetch', 'build', 'test', 'deploy']

Each key lists what must run before it, and a cycle raises CycleError instead of looping forever.

Questions about Python Standard Library Cheat Sheet

What is the difference between a list and a deque in Python?

A list is a dynamic array: indexing is O(1) and appending or popping at the end is amortized O(1), but inserting or removing at the front shifts every element, so list.pop(0) and list.insert(0, x) are O(n). collections.deque is a linked structure of fixed-size blocks with O(1) appends and pops at both ends, which makes it the right queue for breadth-first search or a sliding window, and deque(maxlen=n) discards the oldest items automatically. The trade-off is that indexing into the middle of a deque is O(n), so keep a list when you need random access.

When should I use lru_cache instead of cache?

functools.cache, added in Python 3.9, is an unbounded memoizer equivalent to lru_cache with maxsize set to None: it keeps every result forever, which suits pure recursive functions such as a memoized Fibonacci. lru_cache with a numeric maxsize keeps only the most recently used results and evicts the rest, so memory stays bounded when the space of inputs is large. Both require hashable arguments and are shared by all callers. On methods they also keep instances alive, so prefer module-level functions, or cached_property for per-instance values.

How do I work with dates and time zones in Python?

Use timezone-aware datetimes everywhere. datetime.now(timezone.utc) gives the current UTC time, and zoneinfo, in the standard library since 3.9, provides real IANA zones such as Europe/Berlin with daylight saving rules. Convert between zones with astimezone, serialize with isoformat, and parse back with datetime.fromisoformat, which accepts most ISO 8601 strings from Python 3.11. Avoid utcnow, which returns a naive value and is deprecated since 3.12, and never mix naive and aware values: ordering comparisons between them raise TypeError.

Is a Python dict ordered?

Yes. Since Python 3.7 the language guarantees that a dict preserves insertion order, so iterating, printing or serializing it yields keys in the order they were first added. Updating an existing key keeps its position, while deleting and re-adding it moves it to the end. OrderedDict is still useful for its extra methods, move_to_end and popitem with last=False, which make an LRU cache trivial, and because two OrderedDicts compare equal only when their order also matches. Sets, by contrast, make no ordering guarantee at all.