Python tips

A short reference of things I reach for and do not use often enough to remember. Nothing here is obscure; the point is having it in one place. Python proper covers the language.

Attribute and name checks

hasattr(obj, "name")

Checks whether an attribute exists. Worth preferring getattr(obj, "name", default) when you want the value anyway — one lookup instead of two, and it reads better.

"variable_name" in locals()

Checks whether a name is bound in the current scope. Useful when debugging, and a sign of a design problem in production code — if you do not know whether a variable is defined, control flow has become hard to follow, and initialising it to None up front is the fix.

Safe lookups in mappings

value = mapping.get("key", default_value)

Clearer than an if key in mapping guard, and one lookup rather than two. This is the workhorse for parsing configuration and metadata, where keys are optional by nature.

For nested structures the chained form gets ugly quickly:

value = config.get("outer", {}).get("inner", default)

The empty-dict default is what keeps this from raising when outer is missing. Beyond two levels, a Pydantic model is the better answer — it validates the shape once and gives real attribute access afterwards, instead of scattering defaults through the code.

Mutable default arguments

def f(items=None):
    items = items or []

Not def f(items=[]). The default is evaluated once at definition, so a mutable default is shared across every call and accumulates state between them. This is the classic Python bug, it produces behaviour that looks like memory corruption, and it still catches people who have known about it for years.

See also: Python and Pydantic.