Why L=[] as a Python default argument keeps growing: defaults are built once, at def time
Call def f(a, L=[]) three times and the list keeps growing. What the Python docs say about when defaults are evaluated, __defaults__, the None pattern and dataclass default_factory.
What does this print?
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
If each call got a fresh list, you would see [1], [2], [3]. It actually prints [1], [1, 2], [1, 2, 3]. The official Python tutorial carries this exact example under an “Important warning” heading. It is defined behaviour, not a bug.
This article follows the Python 3.15.0 documentation as checked on 10 October 2026. The evaluation rule for defaults described here is the same throughout Python 3. The one version-dependent detail is in the dataclass section.
Defaults are evaluated when the def statement runs
The function definitions section of the language reference says that default parameter values are evaluated from left to right when the function definition is executed, and that the same pre-computed value is used for each call.
def is a statement that executes, not a declaration. When a module is imported, or a script reaches that line, Python builds the function object, evaluates the expressions to the right of each =, and attaches the results to the function. A call does not evaluate those expressions again; it binds the stored object to the parameter.
So there is exactly one empty list behind L=[] per function. Every call that omits the argument receives that list, and whatever append added is still there on the next call.
Another tutorial example shows the same rule:
i = 5
def f(arg=i):
print(arg)
i = 6
f() # 5
i was 5 when the def ran, so the default is 5. Rebinding i to 6 afterwards does not touch it.
Looking at the function object
The computed defaults live on the function object as a tuple in __defaults__. The data model documentation describes it as a tuple containing default values for the parameters that have defaults, or None if none do. Defaults for keyword-only parameters are kept separately in the __kwdefaults__ dictionary.
After the three calls to f(a, L=[]) above, f.__defaults__ would hold ([1, 2, 3],). That is where the default “remembers” things between calls. If a function seems to carry hidden state while you debug, printing this attribute is the quickest check.
Which defaults cause trouble
Sharing the default is not a problem in itself. The trouble starts when the function changes the shared object. The FAQ notes that immutable objects such as numbers, strings, tuples and None cannot be changed and are safe, while mutable ones such as dictionaries, lists and class instances lead to confusion. The tutorial’s warning names lists, dictionaries and “instances of most classes”.
The forms you are likely to meet:
- A function like
def add(item, items=[])that callsappendorupdateon the collection it receives. - A constructor
def __init__(self, tags=[])that storesself.tags = tags. Every instance created without that argument shares one list. - A function like
def log(msg, when=datetime.now())that wants the call time as its default. The time is computed once, when thedefruns, so every later call records the same moment.
The last case is about when the expression runs rather than about mutability. Both come from the same rule: a default expression runs once, at definition time.
Take None and build the object inside
The reference, the tutorial and the FAQ all recommend the same fix. Use None as the default, test for it in the body, and create the new object there.
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
Now [] runs on every call, so each call that omits the argument gets its own list. The timestamp case works the same way: accept when=None and call datetime.now() in the body.
Write the test as if L is None. Some code shortens it to L = L or [], but that replaces every falsy value, not only None. If a caller passes an empty list in order to collect results, the function appends to a new list instead, and the caller’s list stays empty.
When None is itself a meaningful argument and you need to tell it apart from “not passed”, create a dedicated object at module level, such as _MISSING = object(), use it as the default and compare with is. Nothing else can produce that object, so a caller cannot pass it by accident.
Sharing on purpose
The FAQ adds that the behaviour can be useful, and gives a memoization example that remembers results of an expensive function:
def expensive(arg1, arg2, *, _cache={}):
if (arg1, arg2) in _cache:
return _cache[(arg1, arg2)]
result = ... # expensive computation
_cache[(arg1, arg2)] = result
return result
Placing _cache after * makes it keyword-only, and the leading underscore marks it as internal. The FAQ says a global variable holding a dictionary would work too and calls it a matter of taste. To a reader who does not know the intent, this looks exactly like the bug above, so leave a comment if you do it. If memoization is the goal, the standard library also has the functools.cache (since 3.9) and functools.lru_cache decorators.
dataclass blocks part of the problem
In a @dataclass, a field’s default becomes a default argument of the generated __init__, so the same sharing can happen. According to the dataclasses documentation, the decorator raises ValueError when it finds an unhashable default, on the assumption that an unhashable value is mutable.
from dataclasses import dataclass, field
@dataclass
class D:
x: list = [] # ValueError
@dataclass
class D:
x: list = field(default_factory=list) # a new list per instance
This check changed in Python 3.11. Up to 3.10 it rejected only objects of type list, dict and set; from 3.11 it rejects any unhashable object. The documentation itself calls this a partial solution. A mutable object that is hashable gets through, so when a field needs a mutable default, passing a zero-argument callable to default_factory is the reliable route.
Plain functions and classes get no such check. def f(L=[]) is defined without any warning, so it has to be caught in code review or by a linter.
Summary
- A default expression is evaluated once, when the
defruns, and that object is reused by every call. - If the function changes the default object, the change carries over to the next call. Lists, dictionaries and most class instances are affected.
- Default to
Noneand build a new object in the body withif x is None:. - In a dataclass, use
field(default_factory=...).
References
Checked on 10 October 2026 (Python 3.15.0 documentation)
- The Python Language Reference: 8.7. Function definitions
- The Python Tutorial: 4.9.1. Default Argument Values
- Programming FAQ: Why are default values shared between objects?
- The Python Language Reference: 3. Data model (function.__defaults__)
- dataclasses: Mutable default values
- functools: cache, lru_cache