Python class inheritance and __dict__ lookup [dupl

2019-02-24 20:13发布

问题:

This question already has an answer here:

  • python get only class attribute no superclasses 3 answers

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!

回答1:

@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 it's 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 it's base classes - note that means it is possible to shadow a class variable in a subclass.



回答2:

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 to C.__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.