Default arguments, object sharing, name lookup and others
anton muhin
antonmuhin at rambler.ru
Mon Dec 22 11:30:44 EST 2003
Maciej Sobczak wrote:
> Hi,
>
> Playing around with the Python Tutorial I found the following definition:
>
> def f(a,L=[]):
> L.append(a)
> return L
>
> then:
>
> f(1)
> f(2)
> f(3)
>
> will accumulate the values appending them to the *same* list.
>
> Now:
>
> def f(a,s=''):
> s = s + a
> return s
>
> f('hello')
> f('world')
>
> This will not cause value accumulation.
> Interestingly, this will neither:
>
> def f(a,L=[]):
> L = L + [a]
> return L
>
> which is most confusing for me.
>
> I do not understand how this works (the first one).
> I would like to ask you for some explanation, especially:
> - where is the object stored if it is shared between subsequent calls?
> how it is found?
> - why does it work for lists and not for strings?
> - why does it work for lists only when the append method is used?
>
> My "native" language is C++. Feel free to use analogies, where appropriate.
>
> Thank you very much for any light,
>
It' one of most famous Python's traps. Consider the following:
def foo1(a, L = []):
print id(L)
L = L + [a]
print id(L)
return L
def foo2(a, L = []):
print id(L)
L.append(a)
print id(L)
return L
def foo3(a, L = ''):
print id(L)
L += a
print id(L)
return L
print 'foo1'
foo1('a')
print
print 'foo2'
foo2('a')
print
print 'foo3'
foo3('a')
print
id returns an object's id, usually it's an address.
The code produces:
foo1
8276816
8276848
foo2
8276144
8276144
foo3
7774264
7919296
You can note, that only foo2 doesn't change L's id. That's the
problem---each call populates the same L.
In more details:
L = L + [a] creates a new list
L.append(a) modifies a list in-place
s = s + a creates a new string. BTW, strings in Python are immutable.
How to cope with it. First of all, immutable default parameters
prefered. If you need a mutable one, usual trick is somehting like this:
def foo(a, L = None):
if L is None:
return [a]
else:
return L + [a]
Or, in most of the cases, shorter:
def foo(a, L = None):
return (L or []) + [a]
For more information you can search the group---this question is really
popular one ;)
regards,
anton.
More information about the Python-list
mailing list