Looking at a.__dict__
or vars(a)
gives you attributes of a
, which is an instance. That instance initially has no attributes of its own. The attribute a
that you created in your class definition is an attribute of the class itself, not of its instances. Later when you do a.b = 123
, you create an attribute just on the instance, so you can see it in the instance __dict__
. You will see the attribute a
if you look at C.__dict__
.
When you do print a.a
, Python dynamically finds the attribute a
on the class C
. It sees that the instance doesn't have an attribute a
, so it looks on the class and finds one there. That is the value that is printed. The class attribute is not "copied" to the instance when the instance is created; rather, every individual time you try to read the instance attribute, Python checks to see if it exists on the instance, and if not it looks it up on the class.