今天,我读到了super 的官方文档.
其中提到多重继承将由__mro__
一个类的属性。
所以我做了一些实验,但结果令我惊讶。
# CODE PART
class GrandFather(object):
def p(self):
print "I'm old."
class Father(GrandFather):
def p(self):
print "I'm male."
class Mother(object):
def p(self):
print "I'm female."
class Son(Father, Mother):
def p(self):
print "busy, busy, crwaling. "
# EXPERIMENT PART
In [1]: Son.__mro__
Out[1]: (__main__.Son, __main__.Father, __main__.GrandFather, __main__.Mother, object)
In [2]: Father.__mro__
Out[2]: (__main__.Father, __main__.GrandFather, object)
In [3]: Mother.__mro__
Out[3]: (__main__.Mother, object)
In [4]: GrandFather.__mro__
Out[4]: (__main__.GrandFather, object)
In [5]: s = Son()
In [6]: super(Son, s).p()
I'm male.
In [7]: super(Father, s).p()
I'm old.
In [8]: super(Mother, s).p()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-ce4d0d6ef62d> in <module>()
----> 1 super(Mother, s).p()
AttributeError: 'super' object has no attribute 'p'
In [9]: super(GrandFather, s).p()
I'm female.
以下是我上面提到的官方文档的一部分,它说:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
The __mro__ attribute of the type lists the method resolution search order
used by both getattr() and super().
The attribute is dynamic and can change whenever the inheritance hierarchy is updated.
If the second argument is an object, isinstance(obj, type) must be true.
通过结合这篇文档和我的实验结果。最令人困惑的部分是当调用时super(GrandFather, s).p()
它称为p()
of Mother
, but Mother
不在GrandFather
's __mro__
,并且它的顺序非常低Son
's __mro__
.
稍微思考了一下之后。我得到了一个看似合理的解释,表明官方文档的不完整或缺陷:
也就是说,当使用 withsuper(type, instance)
, the super
函数将从__mro__
的属性class
来自谁你的instance
是构建,但不是__mro__
的属性type
你传递到super
,即使它满足isinstance(instance, type)
健康)状况。
那么当你输入时发生了什么super(Class, instance)
is:
- Python 检查是否
isinstance(instance, Class)
是真的。
- Python 找到
__class__
的属性instance
,
得到instance.__class__
's __mro__
属性。
- Python 查找索引
Class
你传递到super
in the __mro__
步骤2中的元组。
- Python将step3的索引加1,用它来获取对应的类
__mro__
步骤2的元组,并返回该对应类的超级委托。
- 如果步骤4中的索引超过长度
__mro__
步骤2的最后一堂课的代表__mro__
返回step2的,即object
class.
我的理解对吗?
如果我错了,正确的机制是什么super
相互作用type
's __mro__
?
如果我是对的,我应该如何提出 python 官方文档修改的问题?
因为我认为有关此项目的当前版本可能会产生误导。
PS:这个测试是由Python 2.7.6 within IPython 3.2.1
.