Как работает процесс поиска атрибутов Python?

Когда я говорю «процесс поиска атрибутов python», я имею в виду :, что делает python, когда вы пишете x.foo??

Поискав в Интернете, я не нашел много документов по этому поводу, одна из лучших статей, которые я нашел, возобновила процесс до следующих шагов (вы можете увидеть полную статью здесь)

  1. Если attrname является специальным атрибутом (, то есть Python -предоставил атрибут )для имени объекта, верните его.
  2. Проверьте имя объекта. __класс __. __dict __для атрибута. Если он существует и является дескриптором данных -, вернуть результат дескриптора. Поиск по всем базам имени объекта. __класс __для того же случая.
  3. Проверьте имя объекта. __dict __для имени атрибута и возврата, если он найден. Если имя объекта является классом, ищите также его базы. Если это класс и в нем или его базах существует дескриптор, вернуть результат дескриптора.
  4. Проверьте имя объекта. __класс __. __dict __для атрибута. Если он существует и не является дескриптором данных -, вернуть результат дескриптора. Если он существует и не является дескриптором, просто верните его. Если он существует и является дескриптором данных, нас здесь быть не должно, потому что мы бы вернулись в точку 2. Поиск по всем базам имени объекта. __класс __для того же случая.
  5. Поднимите AttributeError.

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

Я нашел несколько образцов, которые не могут быть объяснены таким образом.Рассмотрим следующий код Python:

class Meta(type):
    def __getattribute__(self, name):
        print("Metaclass getattribute invoked:", self)
        return type.__getattribute__(self, name)

    def __getattr__(self, item):
        print('Metaclass getattr invoked: ', item)
        return None

class C(object, metaclass=Meta):
    def __getattribute__(self, name):
        print("Class getattribute invoked:", args)
        return object.__getattribute__(self, name)

c=C()

Теперь проверьте следующие строки с соответствующим выводом:

>> C.__new__
Metaclass getattribute invoked: 


>> C.__getattribute__
Metaclass getattribute invoked: 


>> C.xyz
Metaclass getattribute invoked: 
Metaclass getattr invoked:  xyz
None

>> c.__new__
Class getattribute invoked: (<__main__.C object at 0x013E7550>, '__new__')


>> c.__getattribute__
Class getattribute invoked: (<__main__.C object at 0x01438DB0>, '__getattribute__')
Metaclass getattribute invoked: 
>

>> 

Я сделал следующие выводы: (учитывая, что мы ищем x.foo):

  • __getattribute __отличается для экземпляров и . Для C.foo ()'foo' сначала ищется в C. __dict __и возвращается, если найдено (вместо типа поиска (C ))и для x.foo ()'foo' ищется по типу (x ). __dict __и на x. __дикт __.
  • __Метод getattribute __всегда разрешается для типа (x ), чего я не понимаю здесь, так это последний случай :c. __getattribute __, объект не содержит метод __getattribute__(и C наследуется от объекта ), так почему вызывается метод getattribute метакласса.

Может кто-нибудь объяснить это, пожалуйста?? или, по крайней мере, скажите мне, где я могу найти документацию по этому поводу, спасибо.

24
задан Ariel 26 June 2012 в 15:54
поделиться