is it a bug ??

John Hazen python-list at hazen.net
Thu Jan 30 00:28:34 CET 2003


On Wed, Jan 29, 2003 at 09:54:56PM +0100, brauner joel wrote:
> 
> def f(a=[]):
> 	print a
> 	if len(a)<5:
> 		a.append(1)
> 		f(a)
> 	print a
<snip>
> 
> In other words, the recursive function f seems to make the a list global 
> for all the occurences of the function
> 
> is that normal ?

Contrary to what others have said, this has nothing to do with default
arguments.  It *does* have to do with how functions get their arguments by
reference.

In both f and g, the 'a' that it uses internally to the function is the same as
the list used by its caller, because lists are mutable.  In fact, any
assignment to a mutable object is by reference.  In other words, both variables
"refer to" the same object.  For example:

>>> a
[1, 1]
>>> b=a
>>> a
[1, 1]
>>> b
[1, 1]
>>> id(a)
727120
>>> id(b)
727120
>>> b.append(3)
>>> b
[1, 1, 3]
>>> a
[1, 1, 3]


So, what makes g work the way you expect, is that the '+' operator creates a
*new* list (and a.append just modifies the existing one) :

>>> a=[]
>>> a
[]
>>> id(a)
710992
>>> a=a+[1]
>>> a
[1]
>>> id(a)
727120
>>> a.append(1)
>>> a
[1, 1]
>>> id(a)
727120


You can see that with "a=a+[1]" 'a' now points to a different list.

So, to recurse with a list that you'll be changing, you should pass a copy:

>>> def f(a=[]):
...   print a
...   if len(a) < 5:
...     a.append(1)
...     f(a[:])
...   print a
... 
>>> f()
[]
[1]
[1, 1]
[1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1]
[1, 1]
[1]


-John





More information about the Python-list mailing list