List As Class Attribute
I do not fully understand, what the difference of class attribute integer or list in the following example is: class MyClass(object): a = [1] b = 1 def __init__(self)
Solution 1:
int
values are immutable. You didn't not modify an existing int
, but replaced self.b
with a differentint
value.
list
values are mutable, and list.append
modifies the instance that invokes it. self.a
is modified in-place without replacing the existing list with a new one.
Basically, you cannot predict the behavior of +=
without knowing the type of the value using it. In b = 0; b += 1
, b
refers to a new instance of int
. But in b = []; b += [2,3]
, the existing list is extended (as if you had called b.extend([2,3])
).
Solution 2:
See how you can make it visual with the is statement (NOT with ==):
classMyClass(object):
a = [1]
b = 1def__init__(self):
print(self.a, id(MyClass.a))
print(self.b, id(MyClass.b))
defmodify(self):
self.a.append(2)
print("modfied list attribute:", MyClass.a, id(MyClass.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1print("modfied int attribute:", MyClass.b, id(MyClass.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
print(x.a is y.a) # Trueprint(x.b is y.b) # True
x.modify()
print(x.a is y.a) # Trueprint(x.b is y.b) # Falseclass MyClass(object):
a = [1]
b = 1def__init__(self):
print(self.a, id(MyClass.a))
print(self.b, id(MyClass.b))
defmodify(self):
self.a.append(2)
print("modfied list attribute:", MyClass.a, id(MyClass.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1print("modfied int attribute:", MyClass.b, id(MyClass.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
# Before changing something a and b is a reference to the same objectprint(x.a is y.a) # Trueprint(x.b is y.b) # True
x.modify()
# After that only x.b is a reference to a new object# you accessed the list object that is shared and append a valueprint(x.a is y.a) # Trueprint(x.b is y.b) # False# If you would give x.a a new list it would look like this
x.a = []
print(x.a is y.a) # Falseprint(x.b is y.b) # False# x.a is now not the same list as y.a
Unless you have a reason to use a and b as class attribute i would suggest you to make it instance attributes:
classMyClass(object):
def__init__(self):
self.a = [1]
self.b = 1print(self.a, id(self.a))
print(self.b, id(self.b))
defmodify(self):
self.a.append(2)
print("modfied list attribute:", self.a, id(self.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1print("modfied int attribute:", self.b, id(self.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
print(x.a is y.a) # Falseprint(x.b is y.b) # False
x.modify()
print(x.a is y.a) # Falseprint(x.b is y.b) # False
x.a = []
print(x.a is y.a) # Falseprint(x.b is y.b) # False
Post a Comment for "List As Class Attribute"