A blog by Gary Bernhardt, Creator & Destroyer of Software

Python's default arguments are tricky

19 Dec 2006

Default arguments are evaluated at function definition time, so they're persistent across calls. This has some interesting (and confusing) side effects. An example:

def foo(d=[]):
    d.append('a')
    return d

If you've not tried this before, you probably expect foo to always return ['a']: it should start with an empty list, append 'a' to it, and return. Here's what it actually does:

>>> foo()
['a']
>>> foo()
['a', 'a']
>>> foo()
['a', 'a', 'a']

This is because the default value for d is allocated when the function is created, not when it's called. Each time the function is called, the value is still hanging around from the last call. This gets even weirder if you throw threads into the mix. If two different threads are executing the function at the same time, and one of them changes a default argument, they both will see the change.

Of course, all of this is only true if the default argument's value is a mutable type. If we change foo to be defined as

def foo2(d=0):
    d += 1
    return d

then it will always return 1. (The difference here is that in foo2, the variable d is being reassigned, while in foo its value was being changed.)