# 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

```