Default Argument Inconsistency?
Peter Otten
__peter__ at web.de
Tue Apr 27 05:53:14 EDT 2004
Paul Sweeney wrote:
> The python tutorial gives the following example to demonstrate the fact
> that default args are only evaluated once:
>
> def f(a,L=[]):
> L.append(a)
> return L
>
> print f(1),f(2),f(3)
> [1] [1,2] [1,2,3]
>
> now I'm confident I understand this, but I do not understand how changing
> to the following (whatever the merits of so doing, it was an accidental
> typo)
> results in the output displayed:
>
> def f(a,L=[]):
> if not L: L=[]
The first thing in f() is to check if L evaluates to False, i. e. is empty.
If L is empty the L "the object" is left alone, but L "the identifier" is
bound to a new empty list. So
> L.append(a)
will never operate on the empty list that was provided as default parameter.
> return L
>
>>>> print f(1),f(2),f(3)
> [1] [2] [3]
>
> surely on second entry to f, L == [1], so the "if not L:" should not
> fire?!
While the above works, there is one pitfall that will sooner or later bite
you:
>>> def f(a, L=[]):
... if not L: L = []
... L.append(a)
... return L
...
>>> l1 = ["old"]
>>> f("new", l1)
['old', 'new']
>>> l1
['old', 'new']
>>> l2 = []
>>> f("new", l2)
['new']
>>> l2
[]
>>>
Did you predict the values of l1 and l2 correctly? Congratulations.
I recommend that you adopt the common practice and initialize mutable
parameters with None as the default, which gives you consistent behaviour:
>>> def f(a, L=None):
... if L is None: L = []
... L.append(a)
... return L
...
>>> l1 = ["old"]
>>> f("new", l1)
['old', 'new']
>>> l1
['old', 'new']
>>> l2 = []
>>> f("new", l2)
['new']
>>> l2
['new']
>>>
Peter
More information about the Python-list
mailing list