gotchapythonMajor
Mutable default arguments create shared state between calls
Viewed 0 times
mutable defaultshared statefunction argumentsdefault listdefault dict
Problem
Using a mutable object (list, dict, set) as a default argument causes it to be shared across all calls. def append_to(item, lst=[]): lst.append(item); return lst — calling it twice returns [1, 2] not [2].
Solution
Use None as the default and create a new object inside the function:
def append_to(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
This creates a fresh list on every call. The mutable default is evaluated once at function definition time, not at call time.
def append_to(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
This creates a fresh list on every call. The mutable default is evaluated once at function definition time, not at call time.
Why
Python evaluates default arguments once when the function is defined, not each time it's called. The default object is stored on the function object (func.__defaults__) and reused.
Gotchas
- This also applies to dict and set defaults
- Dataclass fields with mutable defaults need field(default_factory=list)
- Even datetime.now() as a default captures definition time, not call time
Code Snippets
Mutable default argument fix
# BAD
def add(item, lst=[]):
lst.append(item)
return lst
add(1) # [1]
add(2) # [1, 2] — NOT [2]!
# GOOD
def add(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lstContext
When defining functions with list, dict, or set default parameters
Revisions (0)
No revisions yet.