5

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

I've created a Person class which has a name and a list of children. The children are of the same Person class. If I create two Person instances, and add a child to one of the person instances, it gets added to both Person instances. I would assume the child should only be added to the children of person1 and not to person2, but it gets added to both. I must be doing something obvious wrong, but I can't see it.

Similar questions showed people adding the variable definition to the class itself instead of the constructor, but that's not what's happening here. Any help would be much appreciated, it's frying my brain!

See below for code and output:

class Person(object):

    def __init__(self, name, children=[]):
        self.name = name
        self.children = children

    def __repr__(self):
        return '<' + self.name + '>'

    def add_child(self, child):
        self.children.append(child)


def main():
    person1 = Person('Person1')
    person2 = Person('Person2')

    person1.add_child(Person("Person 1's child"))

    print "Person 1's children:", person1.children
    print "Person 2's children:", person2.children

if __name__ == "__main__":
    main()

output of this code is:

Person 1's children: [<Person 1's child>]
Person 2's children: [<Person 1's child>]
Community
  • 1
  • 1
zeefox
  • 53
  • 1
  • 1
  • 3

2 Answers2

11

The problem is in the default value of the children parameter. If you use a mutable object (such as list) and initialize it in the header, it will be initialized just once and then used in all instances.

This has been discussed here.

Try to replace

def __init__(self, name, children=[]):
    self.name = name
    self.children = children

with

def __init__(self, name, children=None):
    self.name = name
    if children is None:
        self.children = []
    else:
        self.children = children
Community
  • 1
  • 1
eumiro
  • 207,213
  • 34
  • 299
  • 261
2

For your init, use this instead:

def __init__(self, name, children=None):
    self.name = name
    if children is None:
        self.children = []
    else:
        self.children = children

What's happening is the two Person objects are using the same list in the background (the list gets bound when the function is defined, not when it's executed). Take a look at this question for a bit more discussion.

Community
  • 1
  • 1
thegrinner
  • 11,546
  • 5
  • 41
  • 64
  • *the list gets bound when the function is defined, not when it's executed* What do you mean ? – asheeshr Jan 25 '13 at 13:21
  • 1
    When the interpreter runs over the script it creates that list once, when it first sees the function, instead of creating a new list each time the function is used. So every time the function is called it will end up using the same list if you don't provide a non-default argument. – thegrinner Jan 25 '13 at 13:24
  • But isnt the list created when the function **is called** the first time rather than when the function *is defined* ? – asheeshr Jan 25 '13 at 13:28
  • I'm going to steal the answer by Miles in the thread I linked above, because it's probably a better way of explaining what's going on: "It's tied to the function object itself. When the function is instantiated (when the declaration is executed), the default parameter expression is evaluated (in the example above, a list literal), and the resulting object is bound to the created function object." – thegrinner Jan 25 '13 at 13:33