Наследование классов Python и поиск __dict__

Допустим, я определяю класс A:

>>> class A:
...     a = 1
...     class SubA:
...         sub_a = { 'a': 1, 'b': 1}

Затем я определяю класс B, который наследуется от A:

>>> class B(A):
...     pass

Теперь проверьте __dict__ из A и __dict__ из B:

>>> A.__dict__
{'a': 1, '__module__': '__builtin__', '__doc__': None, 'SubA': <class __builtin_ _.SubA at 0x02CAA3E8>}
>>> B.__dict__
{'__module__': '__builtin__', '__doc__': None}

Так или иначе, B.__ dict__ не содержит ни "a", ни "SubA". Теперь, если мы делаем:

>>> A.a
1
>>> B.a
1

>>> A.SubA
<class __builtin__.SubA at 0x02CAA3E8>
>>> B.SubA
<class __builtin__.SubA at 0x02CAA3E8>

Первый вопрос: почему B.__ dict__ не содержит "a" и "SubA"? Второй вопрос: почему Ba и B.SubA дают ожидаемые результаты, хотя ни "a", ни "SubA" не входит в __dict__B?

Спасибо!

2 ответа

Решение

@bgporter дал хорошее объяснение поведения, я просто пойду, почему немного:

Если ваша переменная класса была в B.__dict__как бы это функционировало? Каждый подкласс будет иметь свое значение для aнезависимо от значения для A.a - это не то, что вы ожидаете. Переменная класса должна существовать один раз - в этом классе.

Вместо этого Python выполняет поиск класса и, если он не существует, ищет его базовые классы - обратите внимание, это означает, что можно скрыть переменную класса в подклассе.

Вот как работает объектная модель Python:

Класс имеет пространство имен, реализованное объектом словаря. Ссылки на атрибуты класса преобразуются для поиска в этом словаре, например, C.x переводится на C.__dict__["x"] (хотя для классов нового стиля, в частности, есть ряд хуков, которые допускают другие способы определения местоположения атрибутов). Когда имя атрибута там не найдено, поиск атрибута продолжается в базовых классах.

Другие вопросы по тегам