蟒蛇属性查找过程是如何工作的?(How python attribute lookup proces

2019-06-25 19:21发布

当我说“蟒蛇属性查找proccess”我的意思是:什么Python做当你写x.foo?

在网上搜索我没有发现有关此多文档,我找到了最好的论文之一恢复了proccess以下步骤(你可以看到完整的文章在这里 )

  1. 如果attrname是对象名特殊(即Python的提供)属性,其返回。
  2. 检查对象名的attrname .__类__.__ dict__。 如果它存在,是一个数据描述,返回的描述符的结果。 搜索对象名.__ class__的所有基地为同一案件。
  3. 检查对象名.__ dict__为attrname,并返回,如果发现。 如果对象名是一个类,搜索它的基地了。 如果它是一个类和描述符在它或它的基地存在,返回描述符的结果。
  4. 检查对象名的attrname .__类__.__ dict__。 如果它存在,是一个非数据描述,返回的描述符的结果。 如果它存在,而不是一个描述符,只是返回。 如果它存在,是一个数据描述符,我们不应该在这里,因为我们将在2点已经返回的搜索对象名.__ class__的所有基地相同的情况。
  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: <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'>和<型 '对象'>的实例不同。 对于C.foo(),“富”被首先搜索第C .__ dict__并返回如果找到(而不是搜索类型(C))和用于x.foo()“富”上搜索类型(X).__ dict__和在X .__ dict__。
  • __getattribute__方法总是解决的类型(x)的,我不明白这里是最后一种情况:C .__ getattribute__,没有对象包含的方法__getattribute__(和C继承自Object),那么,为什么元类getAttribute方法获得调用。

有人可以解释这个请? 或更少,告诉我在哪里可以找到一些有关此文档,谢谢。

Answer 1:

如果添加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__是越来越调用,以建立所述repr表达的c.__getattribute__ ,以便它可以打印C__name__

顺便说一句, __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


文章来源: How python attribute lookup process works?