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