Assume latest production Python version, unless evidence says otherwise.
list.append).for item in items: item() over item1(); item2(); item3()._name) over public__all__Order: imports -> module constants -> type aliases -> private helpers -> public functions/classes.
Prefer the least powerful construct that fits.
Data:
enum.Enum/IntEnum/StrEnum for a fixed, named set of valuestyping.NamedTuple for a small immutable record; already frozen, hashable, and slotted@dataclass(frozen=True, slots=True) once the type needs field() defaults, __post_init__, inheritance, or must not be usable as a plain tupledict/TypedDict only for dynamic keys or a shape dictated by an external payload (JSON, config); convert at the deserialization boundary rather than passing the mapping inwardBehavior:
typing.Protocol over an ABC or a shared base class; declare the shape you consume instead of growing an inheritance tree@abstractmethod hooks, never as a bare interface declaration; still preferred over a concrete base with NotImplementedError stubsfrom copy import copy
from dataclasses import replace
foo = Foo()
foo = replace(foo, a=1)
foo_b = copy(foo)
replace in a with_(**changes) helper; **kwargs loses type-checker field validation.cursor.advanced(1).replace.slots=True) only for a short-lived local accumulator.NamedTuple, with _replace in place of replace.enum.Enum/enum.IntEnum; members are already namespaced (Foo.A), so don’t prefix values (FOO_A).len(Foo) or iteration instead of a manual COUNT sentinel.FOO_DATA = { Foo.A: {…}, Foo.B: {…}, } ```
uv for packages and environments; never hand-roll pip/venv/poetry, and run commands via uv run rather than activating a venv.uv in setup scripts (official installer if missing) rather than assuming it’s preinstalled.uv run --locked, uv sync --frozen); upgrading (uv lock --upgrade) is a separate, explicit action.--directory/--all-packages explicitly instead of relying on cwd or a single-package assumption.click for argument parsing over argparse or hand-rolled sys.argv handling.<package>/__main__.py, registered as a [project.scripts] entry point in pyproject.toml; invoke it as uv run foo <command>, not uv run python foo/main.py.