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

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

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

  1. Если attrname является специальным (то есть Python-предоставленным) атрибутом для objectname, верните его.
  2. Проверьте имя объекта .__ class __.__ dict__ для attrname. Если он существует и является дескриптором данных, верните результат дескриптора. Найдите все базы имени объекта .__ class__ для одного и того же случая.
  3. Проверьте имя объекта .__ dict__ для имени attrname и верните, если найдено. Если objectname является классом, ищите его базы тоже. Если это класс и существует дескриптор в нем или его основаниях, верните результат дескриптора.
  4. Проверьте имя объекта .__ class __.__ dict__ для attrname. Если он существует и является дескриптором без данных, верните результат дескриптора. Если он существует и не является дескриптором, просто верните его. Если он существует и является дескриптором данных, мы не должны быть здесь, потому что мы вернемся в точке 2. Найдите все базы objectname .__ class__ для одного и того же случая.
  5. Raise 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: <class '__main__.C'> <built-in method __new__ of type object at 0x1E1B80B0> >> C.__getattribute__ Metaclass getattribute invoked: <class '__main__.C'> <function __getattribute__ at 0x01457F18> >> C.xyz Metaclass getattribute invoked: <class '__main__.C'> Metaclass getattr invoked: xyz None >> c.__new__ Class getattribute invoked: (<__main__.C object at 0x013E7550>, '__new__') <built-in method __new__ of type object at 0x1E1B80B0> >> c.__getattribute__ Class getattribute invoked: (<__main__.C object at 0x01438DB0>, '__getattribute__') Metaclass getattribute invoked: <class '__main__.C'> <bound method C.__getattribute__ of <__main__.C object at 0x01438DB0>> >> 

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

  • __getattribute__ отличается для экземпляров <type 'type'> и <type 'object'>. Для C.foo (), «foo» выполняется поиск сначала на C .__ dict__ и возвращается, если найден (вместо поиска типа (C)), а для x.foo () 'foo' выполняется поиск по типу (x) .__ dict__ и на x .__ dict__.
  • Метод __getattribute__ всегда разрешен по типу (x), что я не понимаю здесь, это последний случай: c .__ getattribute__, is not object содержит метод __getattribute__ (и C наследует от объекта), поэтому почему метод metaclass getattribute получает называется.

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

    One Solution collect form web for “Как работает процесс поиска атрибутов python?”

    Если вы добавили print("Metaclass getattribute invoked:", self, name) вы увидите:

     >>> c.__getattribute__ Class getattribute invoked: <__main__.C object at 0x2acdbb1430d0> __getattribute__ Metaclass getattribute invoked: <class '__main__.C'> __name__ <bound method C.__getattribute__ of <__main__.C object at 0x2acdbb1430d0>> 

    __getattribute__ вызывается для создания c.__getattribute__ выражения c.__getattribute__ , так что он может печатать C __name__ .

    __getattribute__ , __getattribute__ работает одинаково для классов и метаклассов; атрибут сначала проверяется на экземпляр, затем на тип экземпляра.

     >>> Meta.foo = 1 >>> C.foo ('Metaclass getattribute invoked:', <class '__main__.C'>, 'foo') 1 >>> c.foo ('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'foo') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __getattribute__ AttributeError: 'C' object has no attribute 'foo' >>> C.bar = 2 >>> c.bar ('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'bar') 2 
    Python - лучший язык программирования в мире.