Reputation: 31
I have following code snippet:
class House:
area = "Munich"
def __init__(self, street, number):
self.street = street
self.num = number
h1 = House("Offenbachstarsse", 123)
h2 = House("Offenbachstarsse", 145)
print(h1.street + ',' + str(h1.num) + ',' + h1.area)
print(h2.street + ',' + str(h2.num)+ ',' + h2.area)
output ** Offenbachstarsse,123,Munich Offenbachstarsse,145,Munich **
h2.area = "Regensburg"
print(h1.street + ',' + str(h1.num) + ',' + h1.area)
print(h2.street + ',' + str(h2.num)+ ',' + h2.area)
output ** Offenbachstarsse,123,Munich Offenbachstarsse,145,Regensburg **
House.area = "Germany"
print(h1.street + ',' + str(h1.num) + ',' + h1.area)
print(h2.street + ',' + str(h2.num)+ ',' + h2.area)
output ** Offenbachstarsse,123,Germany Offenbachstarsse,145,Regensburg **
could someone please explain, how do updates to class attributes work? when an update to class attribute is done using the class, why does it only change the h1 object area and not h2 object area ?
I understand that the class attribute "area" when changed using the object, changes only the value of the class attribute of the used object i.e. h2.area ="Regensburg" updates only h2.area, whereas my expectation was that changes done in the class attribute using the class should be reflected in all the object instances as well. example: House.area = "Germany" would lead to h2.area = "Germany" and h1.area = "Germany". But I see that the h2.area is still showing the local update. Why is that ?
Upvotes: 1
Views: 112
Reputation: 5458
When you did h2.area="Regensburg"
, you created an instance attribute of that name. Just like if you do h2.whatever=123
and it creates a new attribute. The class attribute is still there, just not directly accessible. Do del h2.area
and then print(h2.area)
and see for yourself!
Quick demonstration:
>>> class Test:
... a = 1
...
>>> t1 = Test()
>>> t2 = Test()
>>> t1.a = "this creates an instance attribute"
>>> t1.b = "just like this normally creates an instance attribute"
>>> t1.a
'this creates an instance attribute'
Now, let's check each object's dict dunder:
>>> t2.__dict__
{}
>>> t1.__dict__
{'a': 'this creates an instance attribute', 'b': 'just like this normally creates an instance attribute'}
>>> Test.__dict__
mappingproxy({'__module__': '__main__', 'a': 1, '__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None})
As you can see, t1 has its own attributes stored. t2 doesn't - when we do t2.a, we don't find it so we check class attribute.
And now, for the big reveal:
>>> del t1.a
>>> t1.a
1
>>> t1.__dict__
{'b': 'just like this normally creates an instance attribute'}
We deleted the instance attribute, so we can again see the class attribute when we do t1.a
Upvotes: 1