1

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

consider the following python test.py module:

class Container:
    def __init__(self, str_list=[]):
        self.str_list = str_list

    def from_strings(self, st=""):
        self.str_list.append(st)
        return self

o1 = Container().from_strings(st="o1")
o2 = Container().from_strings(st="o2")
o3 = Container().from_strings(st="o3")

def prnt():
    print("o1's list:"+str(o1.str_list))
    print("o2's list:"+str(o2.str_list))
    print("o3's list:"+str(o3.str_list))

if __name__ == '__main__':
    prnt()

Why is the output of python test.py:

  o1's list:['o1', 'o2', 'o3']
  o2's list:['o1', 'o2', 'o3']
  o3's list:['o1', 'o2', 'o3']

instead of:

  o1's list:['o1']
  o2's list:['o2']
  o3's list:['o3']

(It seems like I am missing why a field (str_list) of different instances in the same module could mix up. A pointer to the python doc explaining this concept would be highly appreciated)

Community
  • 1
  • 1
psvm
  • 57
  • 5
  • 1
    Ah, the old mutable default arg. This is something you will just have to learn about Python. – MikeHunter Nov 18 '12 at 16:19
  • @DSM yes I guess it is along the same lines. I guess it didn't come up in my searches, since I wasn't even suspecting the default argument, but rather thought that the fields mix somehow. – psvm Nov 18 '12 at 16:31

1 Answers1

2

You created an empty list as default value in your constructor:

def __init__(self, str_list=[]):
    self.str_list = str_list

This list is only created once and then shared by all instances. If you wanted a separate list for each instance, you could do something like:

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

Now each instance creates it's own list.

edit:

What is going on?

You have probably used default arguments like 1, or 'foo' and never had a problem. These are immutable objects which can not be manipulated. Whenever you think you do, you get a new instance in stead. The collection of immutable object types includes int, str, tuple, among others.

Now [], a list, is a mutable object which can be manipulated. So whenever you change an attribute on it, it changes the actual object and every reference to it will reflect the changes.

Jesse the Game
  • 2,600
  • 16
  • 21