type.__getattribute__和object.__getattribute__有什么区别?

11 投票
1 回答
1540 浏览
提问于 2025-04-18 09:21

给定:

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__ 只是在 AB 的实例上使用。这是因为 特殊方法是根据类型查找的;对于实例来说,类型就是类。

那么对于类来说,类型是 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__,那么 AB.__mro__ 的一个成员,所以可以在那找到 f

>>> type(B).__mro__
(<class 'type'>, <class 'object'>)
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

撰写回答