Gangmax Blog

Why Does Python Default Arguments Keep State Across Calls?

I notice this when I was reading the JavaScript document here:

The default argument is evaluated at call time. So, unlike (for example) Python, a new object is created each time the function is called.

This is something I didn’t know before. I tested it and that’s true.

1
2
3
4
5
6
7
8
9
10
>>> def test(x, y = []):
... y.append(x)
... return y
...
>>> test(1)
[1]
>>> test(2)
[1, 2]
>>> test(3)
[1, 2, 3]

So I tried searching why this happens and I got some answers here.

It is a feature that pretty much all Python users run into once or twice. The main usage is for caches and the like to avoid repetitive lengthy calculations (simple memoizing, really), although I am sure people have found other uses for it.

The reason for this is that the def statement only gets executed once, which is when the function is defined. Thus the initializer value only gets created once. For a reference type (as opposed to an immutable type which cannot change) like a list or a dictionary, this ends up as a visible and surprising pitfall, whereas for value types, it goes unnoticed.

Usually, people work around it like this:

1
2
3
4
def test(a=None):
if a is None:
a = {}
# ... etc.

The key difference between Python and JavaScript is that, for Python expressions in default arguments are calculated when the function is defined, while for JavaScript they’re calculated when the function is called.

Comments