I was reading the python tutorial from Python Documentation Release 2.7.10 and I came across something like this.
Code
def fun1(a,L=[]):
L.append(a)
return L
print fun1(1)
print fun1(2)
print fun1(3)
def fun2(a,L = None):
if L is None:
L=[]
L.append(a)
return L
print fun2(1)
print fun2(2)
print fun2(3)
Output
[1]
[1, 2]
[1, 2, 3]
[1]
[2]
[3]
Process finished with exit code 0
If the L=[]
in the first function fun1()
is getting called only once , the output of fun1()
is fine. But then why L=None
is getting called every time in fun2()
.
default arguments are evaluated only once. In
fun1
you have the same list which you keep adding to. Infun2
you assign a new[]
to the parameter and then append to it. As any assignment, its scope will be limited to the block it occurred in.When you define a function the values of the default arguments get evaluated, but the body of the function only get compiled. You can examine the result of the function definition via attributes. Theres a
__defaults__
attribute containing the defaults and__code__
attribute containing the body (so these are created when the function is defined).What's happening in the second example is that
None
do get evaluated at definition (it evaluates toNone
duh!), but the code that conditionally assigns[]
toL
only gets compiled and is run each time (the condition passes).L=[]
in the function declaration makes Python essentially do this:L
[]
, let's set this particular[]
aside and use it anytime there's no parameter passed forL
L
, and assign it either the passed parameter or the value we set aside earlierSo, the
[]
part is getting executed once, which creates a list object, which is set aside and kept around, which is why it accumulates changes if you modify it. Exactly the same thing happens withNone
, howeverNone
is not being modified nor is it mutable to begin with, so you're not seeing any weird side effects.None
is still only being "executed" once, and that particularNone
value is set aside just as the list was, it's just that you're not doing anything to theNone
value itself.