8

与えられた:

In [37]: class A:
   ....:     f = 1
   ....:

In [38]: class B(A):
   ....:     pass
   ....:

In [39]: getattr(B, 'f')
Out[39]: 1

さて、それは super を呼び出すか、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'

getattr が行うのに getattribute が行わないのは何ですか?

In [43]: type.__getattribute__(B, 'f')
Out[43]: 1

何?! type.__getattribute__は super を呼び出しますが、objectのバージョンは呼び出しませんか?

In [44]: type.__getattribute__(A, 'f')
Out[44]: 1
4

1 に答える 1

9

クラスを直接操作しています。andのインスタンスobject.__getattribute__のみ使用されます。これは、特別なメソッドが type で検索されるためです。たとえば、型はクラスです。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__for classesを使用すると、 directにはf属性がなく、 のどこにもありません。を使用する場合、は のメンバーなので、次の場所にあります。B ftype(B).__mro__type.__getattribute__AB.__mro__f

>>> type(B).__mro__
(<class 'type'>, <class 'object'>)
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
于 2014-06-10T21:21:29.923 に答える