Default arguments, object sharing, name lookup and others

Skip Montanaro skip at pobox.com
Mon Dec 22 11:42:18 EST 2003


    Maciej> Playing around with the Python Tutorial I found the following
    Maciej> definition:

    Maciej> def f(a,L=[]):
    Maciej>     L.append(a)
    Maciej>     return L

    Maciej> then:

    Maciej> f(1)
    Maciej> f(2)
    Maciej> f(3)

    Maciej> will accumulate the values appending them to the *same* list.

This works because default arguments are evaluated when the function is
defined and stored with the function.  When the function is called, the
default is retrieved.  In this case, the default is a mutable object (a
list), so the same list keeps getting modified.

    Maciej> Now:

    Maciej> def f(a,s=''):
    Maciej>     s = s + a
    Maciej>     return s

    Maciej> f('hello')
    Maciej> f('world')

    Maciej> This will not cause value accumulation.

Nope.  You're rebinding the local variable s.  Try this slight modification:

    def f(a, s=''):
        print id(s)
        s = s + a
        print id(s)
        return s

id() prints the address of the object.  You should see the two print
statements display different addresses.

    Maciej> Interestingly, this will neither:

    Maciej> def f(a,L=[]):
    Maciej>     L = L + [a]
    Maciej>     return L

    Maciej> which is most confusing for me.

Same reason.

    Maciej> - where is the object stored if it is shared between subsequent
    Maciej>   calls?  

Take a look at f.func_defaults.

    Maciej> how it is found?

Index into f.func_defaults based on position in the argument list.  (L is
the zeroth arg with a default, so if missing it gets assigned
f.func_defaults[0].)

    Maciej> - why does it work for lists and not for strings?

Your functions are coded so that the difference is because in one
(L.append(a)) you're modifying the object to which the variable refers,
while in the other (L = L + a or s = s + a) you're rebinding the local
variable.  I think you're asking a slightly wrong question here.  If you
defined:

    def f(a, s=''):
        s += a
        return s

vs

    def f(a, L=[]):
        L += a
        return a

the apparent difference in behavior would be because lists are mutable while
strings are not.

    Maciej> - why does it work for lists only when the append method is used?

It doesn't.  Try L.insert() instead.  You notice similar effects.

Skip





More information about the Python-list mailing list