Back to blog
QualityQUAL0042026-01-303 min

Mutable Default Arguments: Python's Classic Trap

Python evaluates default arguments once, when the function is defined — not each time it's called. If the default is a mutable object like a list or dictionary, every call that uses the default shares the same object.

The classic example

def add_item(item, items=[]): items.append(item) return items

The first call returns ['a']. The second call returns ['a', 'b'] — not ['b']. The default list persists between calls, accumulating state that was never intended.

This is documented in every Python FAQ, taught in every intermediate course, and still written by AI assistants in production code every single day.

Why AI keeps writing this

AI models have seen millions of function signatures with default arguments. The pattern def f(x=[]) is syntactically clean and appears constantly in training data — including in tutorials that demonstrate the bug. The model generates what looks natural, not what's correct.

We see this most often in data processing functions, API handlers that accumulate results, and configuration builders that merge defaults with user input.

What QUAL004 catches

QUAL004 flags any function parameter with a mutable default: empty lists, empty dicts, empty sets, and instances of mutable classes. The fix is always the same pattern:

def add_item(item, items=None): if items is None: items = [] items.append(item) return items

One of those checks where the fix takes ten seconds and the bug it prevents can take hours to track down.

QUAL004 is available with a StableStack license.

pip install stablestack