Published on

Python 3 mutable default argument issue

In Python, a mutable default argument can cause surprising behavior because default arguments are evaluated once, when the function is defined, not each time it is called.

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

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b']  ← surprise
print(add_item("c"))  # ['a', 'b', 'c']

The same items list is reused across calls.

Correct pattern

Use None as the default and create the mutable object inside the function:

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

    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['b']

This issue applies to mutable objects such as list, dict, and set:

# Bad
def f(x, cache={}):
    ...

# Usually safer
def f(x, cache=None):
    if cache is None:
        cache = {}

One nuance: mutable defaults aren't inherently invalid. Sometimes persistent state is intentional—for example, a deliberately shared cache. The bug occurs when you expect a fresh object on every call.