Skip to content
v0.1.0latest release21 skills2 categories3 sub-categories22 tested scripts68 reference docsContact us

Stdlib Power Tools

Reference for python-idiomatic-code-reviewer · 382 lines

Programming / Pythonv1.0.0Updated OCT 20 20265 references1 script

Standard-library modules that replace hand-written loops, helper classes and small dependencies. Each entry gives the before/after and when to reach for it. Examples assume Python 3.9+; newer APIs are tagged.

Contents

  1. collections
  2. itertools
  3. functools
  4. operator
  5. pathlib
  6. contextlib
  7. dataclasses
  8. enum
  9. heapq and bisect
  10. Other quick wins

collections

ToolUse it forReplaces
defaultdict(list)Groupingif k not in d: d[k] = []
CounterFrequencies, top-k, multiset mathsmanual count dicts
deque(maxlen=n)Sliding windows, bounded history, queueslist.pop(0) (O(n))
OrderedDictLRU via move_to_end / popitem(last=False)— (plain dict keeps order otherwise)
ChainMapLayered config lookupmerged dict copies
namedtupleLightweight immutable recordstuples indexed by position
python
from collections import ChainMap, Counter, OrderedDict, defaultdict, deque, namedtuple

# Group chunks by document
by_doc = defaultdict(list)
for chunk in chunks:
    by_doc[chunk.doc_id].append(chunk)

# Label distribution and top tokens
labels = Counter(ex["label"] for ex in dataset)
top_tokens = Counter(tok for text in corpus for tok in text.split()).most_common(20)
labels.update(["positive", "negative"])           # add counts
imbalance = labels.most_common(1)[0][1] / max(labels.total(), 1)   # .total(): 3.10+

# Bounded chat memory: keeps the last 20 turns automatically
history = deque(maxlen=20)
history.append({"role": "user", "content": "hi"})

# Simple LRU cache
class LRU:
    def __init__(self, capacity: int):
        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)

# Layered configuration: CLI > env > file > defaults
config = ChainMap(cli_args, env_config, file_config, DEFAULTS)
model = config["model"]

# Record type
Hit = namedtuple("Hit", ["doc_id", "score"])
best = max(hits, key=lambda h: h.score)

typing.NamedTuple gives the same with type hints:

python
from typing import NamedTuple

class Hit(NamedTuple):
    doc_id: str
    score: float

itertools

FunctionExampleUse case
chain.from_iterableflatten chunks of docsone-level flatten
islicefirst n of a streamhead of a generator / JSONL file
batched (3.12+)batched(texts, 64)API batch limits
pairwise (3.10+)consecutive pairsdeltas, overlaps
groupbygroup sorted dataruns by key
accumulaterunning totalscumulative token counts
producthyperparameter gridsgrid search
combinationspairwise comparisonsduplicate detection
zip_longestalign uneven sequencespadding
count, cycle, repeatinfinite counters / round-robinid generation, key rotation
takewhile, dropwhileprefix/suffix by conditionheader skipping
starmapapply to argument tuplesstarmap(pow, pairs)
teeduplicate an iteratorrarely; prefer a list
python
from itertools import accumulate, chain, combinations, cycle, groupby, islice, product

# Peek at the first 5 records of a huge JSONL file without reading it all
with open("train.jsonl", encoding="utf-8") as f:
    sample = [json.loads(line) for line in islice(f, 5)]

# Grid search over generation params
grid = [dict(temperature=t, top_p=p) for t, p in product([0.0, 0.3, 0.7], [0.9, 1.0])]

# Pack chunks into a context window by cumulative token count
lengths = [len(enc.encode(c.text)) for c in ranked_chunks]
fits = [c for c, total in zip(ranked_chunks, accumulate(lengths)) if total <= budget]

# groupby needs input sorted by the same key
rows.sort(key=lambda r: r["doc_id"])
for doc_id, group in groupby(rows, key=lambda r: r["doc_id"]):
    merge(doc_id, list(group))

# Near-duplicate check over all pairs (O(n^2): small n only)
dupes = [(a.id, b.id) for a, b in combinations(docs, 2) if jaccard(a, b) > 0.9]

# Round-robin over API keys / replicas
endpoints = cycle(["https://a.example", "https://b.example"])
next_url = next(endpoints)

functools

ToolUse it for
cache (3.9+) / lru_cache(maxsize=n)Memoising pure functions (tokenizer lookups, query embeddings)
cached_propertyLazy per-instance computed attributes
partialPre-binding arguments for callbacks / map
reduceFolding (rarely clearer than a loop or sum/math.prod)
wrapsWriting decorators that keep __name__ / __doc__
singledispatchType-based function overloading
total_orderingFill in comparison methods from __eq__ + __lt__
python
import functools
import time

@functools.cache
def get_tokenizer(name: str):
    from transformers import AutoTokenizer
    return AutoTokenizer.from_pretrained(name)

def timed(fn):
    @functools.wraps(fn)                     # keeps fn.__name__, docstring, signature for tooling
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        try:
            return fn(*args, **kwargs)
        finally:
            logger.info("%s took %.1f ms", fn.__name__, (time.perf_counter() - start) * 1000)
    return wrapper

@functools.singledispatch
def to_text(obj) -> str:
    raise TypeError(f"cannot convert {type(obj).__name__}")

@to_text.register
def _(obj: str) -> str:
    return obj

@to_text.register
def _(obj: dict) -> str:
    return json.dumps(obj, ensure_ascii=False)

embed_small = functools.partial(embed, model="text-embedding-3-small")
vectors = list(map(embed_small, texts))

Caching caveats: arguments must be hashable; cached return values are shared, so return immutable objects (tuples, frozen dataclasses); lru_cache on methods keeps instances alive; it does not cache coroutines' results.

operator

python
from operator import attrgetter, itemgetter, methodcaller

hits.sort(key=attrgetter("score"), reverse=True)        # instead of lambda h: h.score
rows.sort(key=itemgetter("doc_id", "chunk_index"))     # multi-key
ids = list(map(itemgetter("id"), records))
stripped = list(map(methodcaller("strip"), lines))

attrgetter/itemgetter are faster than lambdas and read as data.

pathlib

os / globpathlib
os.path.join(a, b)Path(a) / b
os.path.exists(p)p.exists()
os.path.basename(p)p.name
os.path.splitext(p)[0]p.stem (name) / p.with_suffix("") (path)
os.path.splitext(p)[1]p.suffix
os.path.dirname(p)p.parent
os.path.abspath(p)p.resolve()
os.makedirs(d, exist_ok=True)d.mkdir(parents=True, exist_ok=True)
os.listdir(d)d.iterdir()
glob.glob("**/*.md", recursive=True)Path().glob("**/*.md") / rglob("*.md")
open(p).read()p.read_text(encoding="utf-8")
os.remove(p)p.unlink(missing_ok=True) (3.8+)
os.rename(a, b)a.rename(b) / a.replace(b)
os.path.getsize(p)p.stat().st_size
os.walk(d)d.walk() (3.12+)
python
from pathlib import Path

ROOT = Path(__file__).resolve().parent
DATA = ROOT / "data"

def iter_documents(folder: Path, exts=(".md", ".txt")):
    for path in sorted(folder.rglob("*")):
        if path.is_file() and path.suffix.lower() in exts:
            yield path.relative_to(folder).as_posix(), path.read_text(encoding="utf-8")

out = DATA / "embeddings" / f"{run_id}.npy"
out.parent.mkdir(parents=True, exist_ok=True)

Libraries accepting paths should take str | os.PathLike and call Path(p) once at the boundary.

contextlib

ToolUse it for
contextmanagerTurn a generator into a with block (setup/teardown)
asynccontextmanagerSame for async (FastAPI lifespan, pooled clients)
suppress(*excs)Intentionally ignore specific exceptions
ExitStack / AsyncExitStackA dynamic number of resources
closing(obj)Objects with .close() but no context-manager support
nullcontext(x)Optional context managers (lock if threaded else nullcontext())
redirect_stdoutCapture noisy library prints in tests/tools
chdir (3.11+)Temporarily change directory
python
import time
from contextlib import ExitStack, contextmanager, nullcontext, suppress

@contextmanager
def timer(name: str):
    start = time.perf_counter()
    try:
        yield
    finally:
        logger.info("%s: %.2fs", name, time.perf_counter() - start)

with timer("embed corpus"):
    vectors = embed_corpus(texts)

with suppress(FileNotFoundError):
    Path("index.lock").unlink()

def write_shards(paths: list[Path], rows):
    with ExitStack() as stack:
        files = [stack.enter_context(p.open("w", encoding="utf-8")) for p in paths]
        for i, row in enumerate(rows):
            files[i % len(files)].write(json.dumps(row) + "\n")

def maybe_locked(lock=None):
    return lock if lock is not None else nullcontext()

dataclasses

python
from dataclasses import asdict, dataclass, field, replace

@dataclass(frozen=True)
class RetrievalConfig:
    top_k: int = 5
    min_score: float = 0.2
    rerank: bool = True
    filters: dict = field(default_factory=dict)    # never filters: dict = {}

    def __post_init__(self):
        if self.top_k <= 0:
            raise ValueError("top_k must be positive")

base = RetrievalConfig()
strict = replace(base, min_score=0.5)            # copy with changes (immutable update)
payload = asdict(strict)                          # recursive dict for JSON/logging
OptionVersionEffect
frozen=True3.7Immutable, hashable
order=True3.7Generates <, <=, ...
slots=True3.10__slots__: less memory, no typo attributes
kw_only=True3.10All fields keyword-only
field(repr=False)3.7Hide secrets/large arrays from repr

dataclass vs pydantic: use dataclasses for internal values; pydantic at trust boundaries (API payloads, LLM JSON, config files) where validation and coercion are needed.

enum

python
from enum import Enum, Flag, auto

class FinishReason(str, Enum):          # 3.11+: StrEnum
    STOP = "stop"
    LENGTH = "length"
    TOOL_CALLS = "tool_calls"
    CONTENT_FILTER = "content_filter"

reason = FinishReason(choice.finish_reason)     # raises ValueError on unknown values
if reason is FinishReason.LENGTH:
    logger.warning("truncated output")

class Capability(Flag):
    TEXT = auto()
    VISION = auto()
    TOOLS = auto()

caps = Capability.TEXT | Capability.TOOLS
if Capability.TOOLS in caps: ...

Enums give exhaustiveness in match, typo safety, and a single list of valid values for validation.

heapq and bisect

python
import bisect
import heapq

# Top-k without full sort: O(n log k)
top = heapq.nlargest(10, scored_docs, key=lambda d: d.score)

# Merge already-sorted result lists from several shards
merged = list(heapq.merge(shard_a, shard_b, key=lambda d: -d.score))

# Priority queue of pending jobs
jobs: list[tuple[int, str]] = []
heapq.heappush(jobs, (priority, job_id))
priority, job_id = heapq.heappop(jobs)

# Bucket a score into bands with bisect
BANDS = [0.3, 0.6, 0.85]
LABELS = ["low", "medium", "high", "exact"]
label = LABELS[bisect.bisect_right(BANDS, score)]

Other quick wins

ModuleQuick win
jsonjson.dumps(obj, ensure_ascii=False) for non-ASCII text; separators=(",", ":") for compact JSONL
textwrapdedent for prompt constants; shorten(text, 200) for log previews
stringTemplate("$context") for JSON-heavy prompts without brace escaping
reCompile once at module level; named groups (?P<name>...); re.VERBOSE for complex patterns
statisticsmean, median, quantiles(latencies, n=100) for p95/p99
mathisclose, prod, fsum (accurate float sums), dist
timeperf_counter() for durations, never time.time() differences
uuiduuid.uuid4().hex for request ids
hashlibhashlib.sha256(text.encode()).hexdigest() as a stable cache/dedup key (not hash(), which is salted per process)
secretssecrets.token_urlsafe(32) for tokens, never random
concurrent.futuresThreadPoolExecutor(max_workers=8).map(fn, items) for sync I/O fan-out
asyncioSemaphore, TaskGroup (3.11+), timeout (3.11+), to_thread (3.9+)
logginggetLogger(__name__) per module; logger.exception in except
tempfileTemporaryDirectory() for scratch model checkpoints in tests
shutilshutil.which("ffmpeg"), copytree, rmtree, disk_usage
sqlite3Local caches and eval result stores with zero dependencies
argparseCLIs with --help; type=Path, choices=[...]
tomllib (3.11+)Read pyproject.toml / config files
importlib.metadataversion("openai") to log dependency versions
python
import statistics
p50, p95 = statistics.median(latencies), statistics.quantiles(latencies, n=100)[94]

import hashlib
def cache_key(model: str, prompt: str) -> str:
    return hashlib.sha256(f"{model}\0{prompt}".encode()).hexdigest()
More in Python

python-beginner-concept-tutor

Teach Python concepts to beginners heading into AI engineering (data scientists, analysts, students, career switchers): plain-language definitions, analogies, minimal examples, line-by-line walkthroughs, common mistakes, check-your-understanding questions and mini exercises; Socratic hints before solutions; explaining tracebacks; mutable vs immutable, references and aliasing, is vs ==, integer division, floating point, slicing and off-by-one, indentation errors; a staged learning path from variables to calling an LLM API, embeddings and a tiny RAG. Ships a script that lists the concepts a snippet uses in learning order and traces execution step by step like Python Tutor.

python-comprehension-refactorer

Refactor Python loops into list, dict and set comprehensions and generator expressions, and unroll comprehensions that are too clever: filtering, mapping, nested-loop flattening, conditional expressions, walrus in comprehensions, dict inversion, grouping with defaultdict/Counter, lazy generators for sum/any/all/max, streaming large files, itertools (chain, islice, groupby, batched, pairwise, accumulate, product), scoping rules, side-effect anti-patterns and performance (when map/filter or numpy/pandas vectorization win). AI-engineering focus: building prompt lists, batching texts for embeddings, filtering retrieved chunks by score, id->embedding dicts, flattening tool-call results, lazy dataset streaming and token counting.

python-context-manager-writer

Write correct Python context managers and find resource-handling bugs — __enter__/__exit__ semantics and exception suppression, contextlib (contextmanager, asynccontextmanager, ExitStack, AsyncExitStack, closing, aclosing, suppress, redirect_stdout, nullcontext, chdir), async with, re-entrancy, leaked files/connections/clients/pools/locks, and AI-engineering recipes: torch.no_grad/inference_mode/autocast, eval()/train() switches, GPU cache cleanup, token and latency meters, tracing spans, temp env vars, rate-limit semaphores, httpx/aiohttp client lifecycle, FastAPI lifespan, DB/vector-store transactions, atomic checkpoint writes, seeds and agent sandboxes.

python-dataclass-converter

Convert boilerplate Python classes, dicts, tuples and JSON payloads into dataclasses, or into pydantic v2 BaseModel, TypedDict, NamedTuple, attrs or msgspec when that fits better. Covers every @dataclass option (frozen, slots, kw_only, order, unsafe_hash, match_args, weakref_slot), field() (default_factory, init=False, repr, compare, hash, metadata), __post_init__, InitVar, KW_ONLY, inheritance and default ordering, replace(), asdict deep-copy pitfalls, hashing/equality, serialization and validation. AI focus: LLM request/response and chat Message types, RAG chunks with embeddings (numpy eq gotcha), eval records, configs, typed OpenAI/Anthropic JSON.

python-exception-handling-designer

Design and review Python exception handling: custom exception hierarchies with retryable flags, what to catch where, EAFP vs LBYL, chaining with raise ... from, else/finally, logger.exception, add_note, ExceptionGroup and except* with asyncio.TaskGroup, warnings, asserts vs validation, FastAPI error translation, retries with backoff and jitter, timeouts, cancellation, pytest.raises, plus LLM-app failures: 429 rate limits with retry-after, 5xx overloaded, context-length exceeded, content filters, broken streams, malformed JSON repair loops, tool-call errors fed back to the model, partial embedding batch failures, CUDA OOM batch halving, vector DB outages, circuit breakers and model fallbacks.

python-type-hints-annotator

Add accurate, modern type hints to Python and fix mypy / pyright (pyrefly, ty) errors: builtin generics, X | None, TypeAlias and the 3.12 type statement, TypeVar and PEP 695 generics, Protocol, Callable / ParamSpec / Concatenate, TypedDict (Required, NotRequired, ReadOnly), Literal, Final, ClassVar, overload, Annotated, TypeGuard / TypeIs, Self, Never, TypeVarTuple, async types, Iterable vs Sequence vs Mapping, TYPE_CHECKING, stubs, py.typed, gradual strictness. AI-engineering focus: typed LLM message dicts and tool schemas, pydantic vs TypedDict, numpy NDArray, torch / jaxtyping shapes, streaming generators, async clients, callbacks, generic VectorStore protocols, typed config. Ships an AST audit: coverage gate, legacy-typing rewrites, inferred types.