Once-only evaluation of default parameter values function definitions
Michael Geary
Mike at DeleteThis.Geary.com
Tue Apr 13 02:34:45 EDT 2004
Fred Ma wrote:
> From the python tutorial, it's clear that to avoid sharing
> default values between function calls, one has to avoid:
>
> Example#1
> ---------
> def f(a, L=[]):
> L.append(a)
> return L
>
> Instead, one should use:
>
> Example#2
> ---------
> def f(a, L=None):
> if L is None:
> L = []
> L.append(a)
> return L
>
> None has been described a analogous to the NULL value in
> c++. I'm been looking and googling this newsgroup to get
> a clearer explanation of why this works. The tutorial says
> that the default value is only evaluated once. By that, I
> assume that there is some unnamed object that is given the
> value of the 1st and only evaluation of the default expression.
> Every time the function is called without an L parameter, L
> gets the value of this unnamed object.
This is where you went wrong. It looks like you're thinking that the =
operator copies a value into a variable as it might in C++. It doesn't.
Instead, = binds a name to an object.
In C++ terms, think of L as a *reference* to that list (array) object.
> The unnamed object that I imagined should have the value
> [], and L should get set to [] every time that f() is called
> without a value specified for L.
>
> The alternative explanation that I could think of is that L is
> bound to the unnamed object [], and the object itself
> changes values to reflect changes to L i.e. L is now a
> persistent variable, retaining its value between function
> calls unless a value is provided for L in the function call's
> argument list. In the latter case, one can imagine L simply
> being overwritten with the value provided.
Python doesn't have variables. It has names and objects. The = operator
binds a name to an object (i.e. makes the name a reference to an object).
When the function is defined, the [] is evaluated and an empty list object
created. Then, every time the function is called, the local name L is bound
to that object. But, it's bound to the *same* object every time. L doesn't
get a copy of that object; the name L refers directly to that object.
That's why the append() call keeps appending to the list. It's the same list
every time you call the function.
Here's a simpler example:
>>> a = []
>>> b = a
>>> a
[]
>>> b
[]
>>> a.append(1)
>>> a
[1]
>>> b
[1]
>>>
See what happened? The statement 'b = a' didn't make a copy of a and store
it in b. Instead, it made the name b refer to the same object as a. So, when
I said b.append(1), it meant exactly the same thing as if I'd said
a.append(1).
-Mike
More information about the Python-list
mailing list