1

Согласно документации Python 2.7.12, 3.4.2.3. Вызов Descriptors¶:Почему атрибуты атрибутов экземпляров не проверяются атрибутами metaclass?

поведение по умолчанию для доступа к атрибутам, чтобы получить, набор или удалить атрибут из словаря объекта. Например, a.x имеет поисковую цепочку, начиная с a.__dict__['x'], затем type(a).__dict__['x'] и продолжающуюся через базовые классы type(a)исключая метаклассами.

Но почему метаклассы исключены?

Если вы постоянно звоните type(self), независимо от того, какой объект self является объектом экземпляра или объектом типа, вы в конечном итоге получите <type 'type'>. Поэтому я не могу понять, почему метаклассы пользуются этой «привилегией».


Кстати, я немного смущен этой цитаты: Для объектов экземпляра, object.__getattribute__ используются, так что я думаю, что поиск цепь должна выглядеть следующим образом:

  • a.__dict__['x']
  • type(a).__dict__['x']
  • b.__dict__[x] для b в type(a).__mro__
  • type(b).__dict__[x] дляв type(a).__mro__
  • c.__dict__[x] для c в type(b).__mro__
  • ......

Я прав?

+0

Я вижу, что вы экспериментируете с метаклассами и атрибутируете доступ - по какой-либо причине вы не uisng Python 3?Почти любой проект может использовать Python 3 сегодня, и у tehre есть много особенностей/изменений, которые не попали в Python2 – jsbueno

+0

@jsbueno Хм ... Для совместимости, я думаю. Мой колледж (мой одноклассник, на самом деле. Мы вместе работаем над проектом.) Рекомендовал мне сначала изучить Python2, потому что многие модули еще не поддерживают Python3, и они могут не поддерживать его в ближайшем будущем. Мои эксперименты - это понимание того, как Python работает в фоновом режиме лучше, и они будут полезны, если я решит переключиться на Python3 когда-нибудь, верно? –

+0

Я думаю, что «у многих модулей нет поддержки Python 3», это не так, как с 2015 года. Самые важные thngs nowadys действительно работают в Python3, и, прежде всего, для глубокого понимания, которое вы ищете, я бы сказал, что Python3 гораздо более уместен. Окончание линии Python s2 запланировано на 2020 год. Если вы начнете проект сегодня, то есть за 3 года до его переноса - я бы не сказал, что это того стоит. – jsbueno

ответ

1

Это происходит потому, что поиск атрибута ищет все баз из type(a) (type(a).__mro__), а не всех типов из type(a) (type(type(a))).

Кроме того, type(self) не вызывается непрерывно, поэтому поиск цепи выглядит следующим образом:

  • a.__dict__['x']
  • type(a).__dict__['x']
  • b.__dict__[x] for b in type(a).__mro__
  • raise AttributeError

Как @jsbueno мудро указал в комментарии, вторая ep фактически включен в третью. Это потому, что для любого класса, скажем, класс C, C сам по себе является первым элементом в C.__mro__.

+0

На самом деле второй шаг включен в третью - для понимания того, что происходит, 'type (a) .__ dict __ ['x']' проверка включена в 'b .__ dict __ [x] для b в типе (a) .__ mro__ ' – jsbueno

+0

@jsbueno Да, вы правы. Сам класс 'C' является первым элементом в' C .__ mro__'. Ответ отредактирован. –