Skip to content

Stdlib Tour

The Python standard library is large, but a handful of modules appear in almost every serious codebase. This lesson gives you a runnable introduction to five of them: collections, itertools, datetime, json, and pathlib.


collections — specialised container types

Section titled “collections — specialised container types”

The collections module extends Python’s built-in containers with four workhorses you will use daily.

Counter counts hashable objects and supports arithmetic on counts.

from collections import Counter
c = Counter("aabbbcc")
print(c) # Counter({'b': 3, 'a': 2, 'c': 2})
print(c.most_common(2)) # [('b', 3), ('a', 2)]

defaultdict never raises KeyError — missing keys are auto-initialised using a factory you supply.

from collections import defaultdict
dd = defaultdict(list)
dd["fruits"].append("apple") # no KeyError on a fresh key

namedtuple creates lightweight, immutable record types with named fields — more readable than plain tuples and zero overhead versus a regular tuple.

from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y) # 3 4

itertools provides iterator-building blocks that compose well and never materialise the full sequence into memory until you ask.

chain flattens multiple iterables into one stream. islice lazily slices any iterator. groupby groups consecutive equal-key elements — the input must be sorted by the same key first.

import itertools
list(itertools.chain([1, 2], [3, 4])) # [1, 2, 3, 4]
list(itertools.islice(range(100), 5)) # [0, 1, 2, 3, 4]

Playground 1 — collections and itertools

Section titled “Playground 1 — collections and itertools”
import collections
import itertools
# --- Counter ---
words = "the quick brown fox jumps over the lazy dog the fox".split()
c = collections.Counter(words)
print("top 3:", c.most_common(3))
# --- defaultdict ---
dd = collections.defaultdict(list)
for k, v in [("a", 1), ("b", 2), ("a", 3)]:
dd[k].append(v)
print("grouped:", dict(dd))
# --- namedtuple ---
Point = collections.namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print("point:", p, "| x =", p.x)
# --- chain ---
merged = list(itertools.chain([1, 2], [3, 4], [5]))
print("chained:", merged)
# --- groupby (data must be sorted) ---
data = [("a", 1), ("a", 2), ("b", 3), ("b", 4)]
for key, group in itertools.groupby(data, key=lambda t: t[0]):
print(key, list(group))

The datetime module handles dates, times, and the arithmetic between them. datetime.datetime objects are immutable; operations like adding a timedelta return a new object.

The demo below uses a fixed date so the output is always deterministic — a good habit when writing examples or tests.


json — serialisation and deserialisation

Section titled “json — serialisation and deserialisation”

json.dumps converts a Python object to a JSON string; json.loads parses it back. The separators argument lets you strip whitespace for compact output.

import json
s = json.dumps({"key": "value"}, separators=(",", ":"))
# '{"key":"value"}'

import datetime
import json
# Fixed date for determinism
dt = datetime.datetime(2024, 3, 14, 9, 26, 53)
print("pi day:", dt.strftime("%Y-%m-%d %H:%M:%S"))
delta = datetime.timedelta(days=10)
print("plus 10 days:", (dt + delta).date())
# json round-trip
obj = {"name": "Python", "versions": [3, 10, 11]}
s = json.dumps(obj, separators=(",", ":"))
print("serialized:", s)
back = json.loads(s)
print("name:", back["name"], "| latest:", back["versions"][-1])

pathlib — object-oriented filesystem paths

Section titled “pathlib — object-oriented filesystem paths”

pathlib.Path represents filesystem paths as objects with methods and properties, replacing the older os.path string-based approach.

from pathlib import Path
p = Path("/usr/local/lib/python3.12/site-packages/requests/__init__.py")
print(p.suffix) # .py
print(p.stem) # __init__
print(p.parts) # ('/', 'usr', 'local', 'lib', 'python3.12', 'site-packages', 'requests', '__init__.py')
# Building paths with /
project = Path.home() / "projects" / "myapp"
config = project / "config.toml"
print(config)

pathlib manipulates filesystem paths — run this locally; the browser sandbox has no real filesystem.


What does `collections.Counter('aab')` produce?
Why must data be sorted before passing to `itertools.groupby`?
Which `datetime` method formats a date as a string?