Питон - статьи



             

Листинг 2. Тестирование родословной


>>> issubclass(D,C) True >>> issubclass(D,A) True >>> issubclass(A,B) False >>> issubclass(d,D) [...] TypeError: issubclass() arg 1 must be a class

А теперь интересный вопрос, необходимый для понимания различия между базовыми классами и метаклассами: как разрешается атрибут наподобие d.attr. Для простоты, рассмотрим только стандартное правило просмотра, а не "сваливание" в .__getattr__(). Первый шаг в таком разрешении - поискать в d.__dict__ имя attr. Если оно найдено - это все; но если нет, должно произойти что-то фантастическое, как, например:

>>> d.__dict__, d.a5, d.a1

({'a5': 'instance d'}, 'instance d', 'A')

Хитрость, позволяющая найти атрибут, который не прикреплен к экземпляру - поискать его в классе экземпляра, а после этого во всех базовых классах. Порядок, в котором просматриваются производные классы, называется порядком разрешения метода (method resolution order) для этого класса. Вы можете увидеть его с помощью (мета)метода .mro() (но только из объектов класса):

>>> [k.__name__ for k in d.__class__.mro()]

['D', 'C', 'A', 'B', 'object']

Другими словами, обращение к d.attr сначала ищет в d.__dict__, а затем в D.__dict__, C.__dict__, A.__dict__, B.__dict__ и в конце в object.__dict__. Если имя не найдено ни в одном из этих мест, возбуждается исключение AttributeError.

Заметьте, что в этой процедуре поиска метаклассы не были упомянуты ни разу.




Содержание  Назад  Вперед