I bet there is an answer around, but unfortunately, I couldn't find it. When playing with classes, I found the following behaviour:
class C:
i = 1
a = C()
b = C()
d = C()
b.i = 3
d.i = 4
print(C.i) # -> 1
print(a.i) # -> 1
print(b.i) # -> 3
print(d.i) # -> 4
d.i = 1
print(d.i) # -> 1
C.i = 5
print(C.i) # -> 5
print(a.i) # -> 5
print(b.i) # -> 3
print(d.i) # -> 1
Only the instances' class attributes, which weren't changed already, can be altered by changing the Class' class attribute. How is this behaviour internally checked? Is there a name for further reading?
Thanks!
CodePudding user response:
There's nothing specific to "keep track" of.
Simplifying things a bit, an attribute lookup a.i
for class C
's instance a
looks for i
in the instance's __dict__
first, then in the class's (and base classes') __dict__
. (This is explained in more detail here in the context of descriptors.)
Writing an attribute a.i = 5
only writes into the instance's __dict__
. Writing C.i = 10
writes into the class's dict (and thus any instance that didn't have an i
of its own would see 10
.)
>>> class C:
... i = 1
...
>>> a = C()
>>> a.__dict__.get("i")
# (nothing)
>>> C.__dict__.get("i")
1
>>> a.i
1
>>> a.i = 5
>>> a.__dict__.get("i")
5
>>> C.i = 10 # Update i on class
>>> b = C() # New instance with no i of its own
>>> b.i
10
>>> a.i # No change here, we have our own i
5
>>> del a.i # Scrub the instance-specific `i`
>>> a.i
10