16

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

1
  • 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. Commented Apr 12, 2012 at 13:22

2 Answers 2

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)
Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

great illustration of a confusing and common misconception!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.