Let's say I define class A:
>>> class A:
... a = 1
... class SubA:
... sub_a = { 'a': 1, 'b': 1}
Then I define class B that inherits from A:
>>> class B(A):
... pass
Now, check __dict__ of A and __dict__ of B:
>>> A.__dict__
{'a': 1, '__module__': '__builtin__', '__doc__': None, 'SubA': <class __builtin_ _.SubA at 0x02CAA3E8>}
>>> B.__dict__
{'__module__': '__builtin__', '__doc__': None}
Somehow, B.__dict__ contains neither 'a' nor 'SubA'. Now if we do:
>>> A.a
1
>>> B.a
1
>>> A.SubA
<class __builtin__.SubA at 0x02CAA3E8>
>>> B.SubA
<class __builtin__.SubA at 0x02CAA3E8>
First question: why B.__dict__ does not contain 'a' and 'SubA'? Second question: Why B.a and B.SubA give the expected results, although neither 'a' nor 'SubA' is in B's __dict__?
Thanks!
@bgporter has given a good explanation of the behaviour, I'll just go into why a little:
If your class variable was in B.__dict__
, how would it function? Each subclass would have its own value for a
, independent of the value for A.a
- this is not what you would expect. A class variable should exist once - in that class.
Instead, Python does a lookup on the class and if it doesn't exist, then looks up to its base classes - note that means it is possible to shadow a class variable in a subclass.
That's how Python's object model works:
A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g.,
C.x
is translated toC.__dict__["x"]
(although for new-style classes in particular there are a number of hooks which allow for other means of locating attributes). When the attribute name is not found there, the attribute search continues in the base classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With