Reputation: 16450
I am confused about python's evaluation of default function arguments. As mentioned in the documentation (https://docs.python.org/3.6/tutorial/controlflow.html#more-on-defining-functions)
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
results in
[1]
[1,2]
[1,2,3]
But
def f(a, L=[]):
L = L+[a]
return L
print(f(1))
print(f(2))
print(f(3))
results in
[1]
[2]
[3]
If L is evaluated only once, shouldn't both the function return the same result? Can someone explain what am I missing here?
This question is different than "Least Astonishment" and the Mutable Default Argument. That question is questioning the design choice while here I am trying to understand a specific case.
Upvotes: 3
Views: 105
Reputation: 1215
You are not appending but sort of creating a new L
here:
>>> def f(a, L=[]):
L = L+[a] #Here you're making a new list with the default argument and a.
print(id(L))
return L
>>> f(1)
140489350175624
[1]
>>> f(1)
140489349715976
[1]
>>> f(2)
140489349718536
[2]
You can see the id
of L
changes everytime.
But when you use the append
it goes as:
>>> def f(a, L=[]):
L.append(a) #Here you're just appending and NOT making a new list.
print(id(L))
return L
>>> f(1)
140489350175624
[1]
>>> f(12)
140489350175624
[1, 12]
>>> f(3)
140489350175624
[1, 12, 3]
>>>
Read this.
Upvotes: 1
Reputation: 42007
In
L.append(a)
you are appending to the same list object in all function calls, as lists are mutable.
whereas in:
L = L+[a]
you're actually rebinding the name L
to the concatenation of L
and [a]
. Then, the name L
becomes local to the function. So, in each function call L
becomes different after rebinding.
Upvotes: 1