Python类的`__mro__`属性从何而来?

问题描述

假设有一些课程:

class test():
    pass 

(1)Somewhere在SO上,在documentation中,我接下来读:

mro()类实例化时调用,其结果存储在__mro__中。

好的,我仍然很清楚,因为在__mro__中确实存储了一些东西:

Test.__mro__                                                         
Out[48]: (__main__.Test,object)

再次somewhere,我读到了这篇文章

要查找Python搜索属性名称
a)在以下位置找到的__dict__搜索所有元类__mro__ C的__class__
b)如果在步骤a中找到了数据描述符,请调用__get__() 然后退出
c)否则,调用描述符或在__dict__中返回一个值 C自己的__mro__上的班级。
d)调用在步骤a中找到的非数据描述符。
e)否则,返回元类树值

我发现__mro__中没有Test.__dict__

'__mro__' in Test.__dict__                                           
Out[49]: False

因此,根据先前引文的e子句,我想 __mro__应该取自“元类树值”,因此应取自type.__dict__

真的,__mro__中有type.__dict__

["mro:<method 'mro' of 'type' objects>","__mro__:<member '__mro__' of 'type' objects>"]
  1. 那么,上面(1)中提到的关于documentation中存储在mro()属性中的__mro__结果的内容实际上不是这样吗?

  2. <member '__mro__' of 'type' objects>如何变成(__main__.Test,object)

也许您可以显示一些源代码来了解我打Test.__mro__时的真实情况。

解决方法

__mro__“属性”是data descriptor,类似于property。描述符不是从__mro__获取__dict__属性值,而是从另一个位置获取或计算该值。具体来说,<member '...' of '..' objects>表示从VM内部位置获取值的描述符–这与mechanism used by __slots__相同。

>>> class Bar:
...     __slots__ = "foo",...
>>> Bar.foo
<member 'foo' of 'Bar' objects>
>>> 'foo' in Bar.__dict__
True

描述符是无重复继承的,因此不会显式出现在子类上。

>>> class Foo(Bar):
...     __slots__ = ()
...
>>> Foo.foo
<member 'foo' of 'Bar' objects>
>>> 'foo' in Foo.__dict__
False

此类member数据描述符的精确工作由实现定义。但是,从逻辑上讲,它们与使用内部存储器的property相同:

class FooBar:
    def __init__(self,foo,bar):
        # attributes stored internally
        # the "_data" of a member is not visible
        self._data = [foo,bar]

    @property
    def foo(self):
        return self._data[0]

    @foo.setter
    def foo(self,value):
        self._data[0] = value

    @property
    def bar(self):
        return self._data[1]

    @bar.setter
    def bar(self,value):
        self._data[1] = value