0

My question is about why default parameter couldn't be used to distinguish different object.

If I define class M1 as:

class M1:
   id = -1
   list1 = []
   def __init__(self,id,list1 = []):
       self.id = id
       self.list1 = list1
   def insertList(self,element):
       self.list1.append(element)

And use it like:

if __name__ == '__main__':
    m1 = M1(1,[])
    m1.insertList("a",[])
    m1.insertList("b",[])
    m2 = M1(2,[])
    print m2.list1

It will return [] as m2.list1 because list1 isn't shared between m1 and m2.

However, if I 'trust' default parameter when I define M1 object, like below:

if __name__ == '__main__':
    m1 = M1(1)
    m1.insertList("a",[])
    m1.insertList("b",[])
    m2 = M1(2)
    print m2.list1

It will return ['a','b'] as m2.list1 and list1 is shared between different objects.

I know class parameter could be defined as static or object member based on whether it's defined in __init__(self), but why default parameter will influence result?

tshepang
  • 12,111
  • 21
  • 91
  • 136
linpingta
  • 2,324
  • 2
  • 18
  • 36

1 Answers1

3

It's to do with lists being mutable, first-class objects (see "Least Astonishment" and the Mutable Default Argument). It will work if you do this:

def __init__(self, id, list1=None):
    if list1 is None:
        self.list1 = []

An assignment inside the function body will refresh the variable.

Community
  • 1
  • 1
anon582847382
  • 19,907
  • 5
  • 54
  • 57
  • I read a great [blog post](http://www.toptal.com/python/top-10-mistakes-that-python-programmers-make) recently that discussed this in a manner I found especially clear, perhaps it would be useful to you as well. – TML May 11 '14 at 15:09
  • @TML Thank you! I am still trying to figure out first-class objects myself. – anon582847382 May 11 '14 at 15:10