Skip to content Skip to sidebar Skip to footer

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"