2

This is a more a question to gain an understanding. Consider the code below

class MenuItem:
    def __init__(self, title, children = []):
        self.title = title
        self.children = children

item1 = MenuItem('A')
item2 = MenuItem('B')
item2.children.append('C')
print (item1.children)

When run with either python2 or python3:

python test.py                                           [~]
['C']

In this case, the children for an object, defaults to the empty list. children = []. However, if I create two objects, they share the same children list.

I understand that object based types are just a pointer to a more complex object etc, but I don't understand what exactly [] is pointing to. If I change item2.title, that has no effect on item1.title.

If I change the default item to ['X'] for example, I get item1.children = ['X', 'C']

Could someone please explain this behaviour.

Thanks

Anthony

note: The solution is simply to say children = False and self.children = (children if children else [] which then works as expected - I'm just wondering why the behaviour is as above.

Anthony
  • 31
  • 2
  • 1
    Congratulations on coming up with a *realistic* example of the problem. I've been frustrated by most examples of this problem, because they're always in a context that just doesn't make sense. In your case I think the proper solution is to *always* make a *copy* of whatever list is passed in, whether it's the default or not. – Mark Ransom Oct 03 '14 at 15:32
  • In reply to your title: Parameters in Python are always passed by reference, but there are mutable and immutable objects, which is what makes the difference. – Ulrich Eckhardt Oct 03 '14 at 17:34
  • Cheers, my main question what that clearly item1.children and item2.children pointed at the same object, just wasn't sure what. Having read through the duplicate, think I understand. When the function `MenuItem.__init__` is defined, the array `[]` is created and stored as `MenuItem.__init__.__defaults__[0]` Now when a function inherits the default value, what happens is `chilren = MenuItem.__init__.__defaults__[0]`. My confusion came as I thought that `children = []` would be evaluated when the function was called, rather than being evaluated when the function was defined and then stored. – Anthony Oct 03 '14 at 18:28

0 Answers0