type.__getattribute__和object.__getattribute__有什么区别?
给定:
In [37]: class A:
....: f = 1
....:
In [38]: class B(A):
....: pass
....:
In [39]: getattr(B, 'f')
Out[39]: 1
好吧,这个是调用父类的方法,还是在查找方法解析顺序(mro)呢?
In [40]: getattr(A, 'f')
Out[40]: 1
这是正常的。
In [41]: object.__getattribute__(A, 'f')
Out[41]: 1
In [42]: object.__getattribute__(B, 'f')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-42-de76df798d1d> in <module>()
----> 1 object.__getattribute__(B, 'f')
AttributeError: 'type' object has no attribute 'f'
getattribute 和 getattr 有什么不同?getattribute 没有做什么,而 getattr 却做了?
In [43]: type.__getattribute__(B, 'f')
Out[43]: 1
什么?! type.__getattribute__
调用了父类的方法,但 object
的版本却没有?
In [44]: type.__getattribute__(A, 'f')
Out[44]: 1
1 个回答
13
你现在是在直接操作 类。而 object.__getattribute__
只是在 A
和 B
的实例上使用。这是因为 特殊方法是根据类型查找的;对于实例来说,类型就是类。
那么对于类来说,类型是 type
:
>>> class A:
... f = 1
...
>>> class B(A):
... pass
...
>>> type(B)
<class 'type'>
所以使用的是 type.__getattribute__
:
>>> type.__getattribute__(B, 'f')
1
而 object.__getattribute__
在实例上工作得很好:
>>> object.__getattribute__(B(), 'f')
1
对于实例,属性首先会在类上查找(如果是 数据描述符 的话),然后在实例上查找,如果实例没有这个属性,就会按照方法解析顺序(MRO)在类的继承层次中查找。这就是 object.__getattribute__
的工作。因此,object.__getattribute__
会查看第一个参数(例如 self
,即实例对象)中的属性,并且查看 type(self).__mro__
中的对象。
对于类,属性是在类本身及其所有基类上查找的;type.__getattribute__
直接查看 self.__mro__
来获取这些属性;这里的 self
是一个类对象。
如果你对 类 使用 object.__getattribute__
,那么在 B
上没有 f
属性 直接,而且在 type(B).__mro__
中也找不到 f
。如果你使用 type.__getattribute__
,那么 A
是 B.__mro__
的一个成员,所以可以在那找到 f
:
>>> type(B).__mro__
(<class 'type'>, <class 'object'>)
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)