AnyCompiler
← Blog

September 11, 2026

Why Is My Python List Changing When I Didn't Touch It?

If you've ever written a function with a list as a default argument and watched it mysteriously grow across unrelated calls, you've hit one of Python's most common gotchas — and it's not a bug in Python, it's how default arguments actually work.

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

print(add_item("apple"))
print(add_item("banana"))
Output
['apple']
['apple', 'banana']

The second call, add_item("banana"), returns ['apple', 'banana'] — not ['banana'] like you'd probably expect. Nothing about the second call mentions the first one, so what's actually happening?

Default arguments are evaluated once, not per call

Python evaluates a function's default argument values exactly once, when the function is defined — not each time the function runs. def add_item(item, items=[]) creates ONE list object at definition time, and every call that doesn't pass its own items argument shares that exact same list. append() then mutates that shared object on every call.

The fix: use None as the default, and create the list inside

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

print(add_item("apple"))
print(add_item("banana"))
Output
['apple']
['banana']

Now items=None is the default (an immutable value, safe to reuse), and a fresh, empty list is only created inside the function body when the caller didn't supply their own. Each call that relies on the default now gets its own independent list.

This exact pattern — mutable default arguments — applies to dictionaries and sets too, not just lists. For a closer look at how Python handles arguments and parameters, see the Functions lesson in our free Python course.