1

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 ?

3

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.