Pow*_*ool 5 python inheritance constructor multiple-inheritance
我试图理解多重继承(即方法解析顺序的C3算法)如何在Python中工作.以下经典钻石依赖的玩具示例给出了违背我直觉的结果.
特别是,我注意到以下内容:
A并AA有super将呼叫Base,则输出是:<B> <A> <AA> <Base> </Base> </AA> </A> </B>.(1)被注释掉(即没有调用Base构造函数A)时,输出就是<B> <A> </A> </B>.(2)被注释掉(即没有调用Base构造函数AA)时,输出就是<B> <A> <AA> </AA> </A> </B>.(1)并被(2)注释掉时,则输出为<B> <A> </A> </B>.我的问题是:
A在显式调用构造函数之前在构造函数中被中断Base,跳转到("recurses into")AA构造函数(就好像AA将从中派生A),然后进入Base,然后退出.这是怎么回事?(我理解MRO B->A->AA->Base来自C3要求,即在父类之前调用子类.)AA永远不会调用构造函数,尽管在案例3中它被调用?Base没有调用构造函数,尽管在AA(情况2)/ A(情况3)的构造函数中有显式调用?(在例1中,我按照预期调用它.)以下是课程的MRO:
B:(<class '__main__.B'>, <class '__main__.A'>, <class '__main__.AA'>, <class '__main__.Base'>, <type 'object'>)A:(<class '__main__.A'>, <class '__main__.Base'>, <type 'object'>)AA:(<class '__main__.AA'>, <class '__main__.Base'>, <type 'object'>)Base:(<class '__main__.Base'>, <type 'object'>)码:
#!/usr/bin/env python
# Using Python 2.7
class Base(object):
def __init__(self):
print '<Base>',
super(Base, self).__init__()
print '</Base>',
class A(Base):
def __init__(self):
print '<A>',
super(A, self).__init__() # (1)
print '</A>',
class AA(Base):
def __init__(self):
print '<AA>',
super(AA, self).__init__() # (2)
print '</AA>',
class B(A, AA):
def __init__(self):
print '<B>',
super(B, self).__init__()
print '</B>',
if __name__ == '__main__':
obj = B()
Run Code Online (Sandbox Code Playgroud)
您不应该将 \xe2\x80\x99t 视为super对继承链中下一个 \xe2\x80\x9cup\xe2\x80\x9d 的函数调用。相反,如果使用得当,super将确保 MRO 中的所有函数都按该顺序调用。但为了实现这一点,该链的每个部分都需要进行超级调用。
A因此,如果您删除其中任一中的超级调用,AA则链会中断。根据您删除的内容,链会在A或处中断AA:
B, A, AA,BaseA):B,AAA);B, A,AA因此,您应该记住在所有涉及的类型中始终一致地使用 super 才能使其正常运行。
\n\n如果您想了解有关 的更多信息super,您应该查看今年\xe2\x80\x99s PyCon 上的 Raymond Hettinger\xe2\x80\x99s 演讲 \xe2\x80\x9cSuper 被认为是超级!\xe2\x80\x9d 。它解释得很好,并且还有一些易于理解的示例(涉及真人!)。
引用他那次演讲的内容(我的转录和强调):
\n\n\n\n\n\n
superPython 中最大的问题是什么\xe2\x80\x99 ?它\xe2\x80\x99s不是它的设计。我认为它的设计是完美的,它很漂亮,Guido 做得非常出色。问题是名称,它不应该被称为\xe2\x80\x9csuper\xe2\x80\x9d。为什么不?答案是,如果你用任何其他语言学习 super,它的作用与 Python 的作用是不同的。
\n\n[\xe2\x80\xa6] 它在其他语言中的作用是什么?在其他语言中,它会打电话给你的父母。[\xe2\x80\xa6] 继承,无论什么时候打电话
\nsuper都是给父母打电话。但 Python\xe2\x80\x99s 做了一些不同的事情。它确实呼唤父母,但不是你的父母。当你打电话时super,谁的父母会接到电话?它不是你的祖先,它\xe2\x80\x99是你的孩子\xe2\x80\x99的祖先。
| 归档时间: |
|
| 查看次数: |
1766 次 |
| 最近记录: |