15

Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument

Can anyone explain the following strange behaviour?

I have the following class:

class Zoo:
    def __init__(self,alist=[]):
        self.animals = alist

    def __len__(self):
        return len(self.animals)

    def add(self,a):
        self.animals.append(a)

and when I do the following,

In [38]: z=Zoo()
In [39]: z.add(2)
In [40]: z.add(23)
In [41]: len(z)
Out[41]: 2

In [42]: z2=Zoo()

In [43]: len(z2)
Out[43]: 2

Why is z2.animals not an empty list?

Thanks, Matthias

Community
  • 1
  • 1
thias
  • 2,290
  • 3
  • 20
  • 20
  • 2
    Maybe he did not know what to search for? Sometimes it's hard to come up with the right search terms, if you don't know the terms. – hopla Apr 12 '12 at 13:22

2 Answers2

16

You are mutating the default argument in your constructor (you are just copying a reference to the same list into each of your instances). You can fix this as follows:

class Zoo:
    def __init__(self,alist=None):
        self.animals = alist or []

    def __len__(self):
        return len(self.animals)

    def add(self,a):
        self.animals.append(a)
Steve Mayne
  • 22,285
  • 4
  • 49
  • 49
7

The default argument list is the same object for all instances, hence assigning it to a member just assigns a reference to the same object.

here's an example:

>>> class foo():
...   def __init__(self, x = []):
...       print id(x)
... 
>>> x = foo()
140284337344168
>>> y = foo()
140284337344168
>>> z = foo()
140284337344168

you can see that x is the same object in all instances.

Not_a_Golfer
  • 47,012
  • 14
  • 126
  • 92