views:

309

answers:

2

Edited: Why is there a different output in these two cases?

class foo:
   bar = []
   def __init__(self,x):
           self.bar += [x]

class foo2:
   bar = []
   def __init__(self,x):
           self.bar = self.bar + [x]

f = foo(11)
g = foo(12)

print f.bar
print g.bar

f = foo2(11)
g = foo2(12)
print f.bar
print g.bar
+14  A: 

As it turns out,

listvar += list

is interpreted as adding the elements of list to the existing list referenced by listvar, while

listvar = listvar + list

is interpreted as creating a new list which is the concatenation of listvar and list, and then storing that new list in listvar - overwriting the reference to the previous list.

Hence why you get different results - in the first case, self.bar is shared by both classes, and thus the init functions for both add to the same list, because no new list is ever created. In the second case, each initializer creates a new list, and thus f and g wind up with different lists stored.

An easy way to see this is the following:

a = [1]

b = a
c = a

b = b + [2]
c += [3]

print a,b,c     # Results in [1, 3] [1, 2] [1, 3]
Amber
Yep, you're right. I've removed my post :)
rslite
The thing that got me was that for foo2 the assignment creates an instance variable which masks the class variable (print foo2.bar will show the empty class variable). In the first case the class variable is used all along and nothing new is created.
rslite
+1  A: 

Dav's explained what's going on. IMO this is a clearer implementation as it is less prone to misunderstanding:

class Foo:
   bar = []
   def __init__(self, x):
           self.bar.append(x)
mhawke