我读过Expert Python Programming,它有一个多继承的例子。书的作者已经解释过,但我不理解,所以我想有另一种观点。
该示例显示对象B
已创建两次!
请你给我一个直观的解释。
In [1]: class A(object):
...: def __init__(self):
...: print "A"
...: super(A, self).__init__()
In [2]: class B(object):
...: def __init__(self):
...: print "B"
...: super(B, self).__init__()
In [3]: class C(A,B):
...: def __init__(self):
...: print "C"
...: A.__init__(self)
...: B.__init__(self)
In [4]: print "MRO:", [x.__name__ for x in C.__mro__]
MRO: ['C', 'A', 'B', 'object']
In [5]: C()
C
A
B
B
Out[5]: <__main__.C at 0x3efceb8>
书作者说:
这是由
A.__init__(self)
调用引起的,该调用是使用 C实例,从而使super(A, self).__init__()
调用B
的构造函数
我没有理解这一点是A.__init__(self)
调用将super(A, self).__init__()
调用B
的构造函数
答案 0 :(得分:8)
$scope.modelPromise = $http.get('some-url').then(function(response) {
$scope.model = response.data;
});
// somewhere else
$scope.modelPromise.then(function(response) {
// do stuff here
});
只是意味着&#34;紧接着#34;行,mro super()
。因此['C', 'A', 'B', 'object']
的下一行是A
。
根据称为C3 linearization的算法计算mro。
当您使用B
时,Python就会遵循此顺序。当你写上课程super()
时,你还不知道下一课是哪一课。只有在您创建具有多重继承的课程A
并运行您的程序后,您才能获得mro并且知道&#34; C
的下一步是什么。
对于您的示例,它意味着:
A
调用C()
的{{1}},其中__init__()
调用C
__init__()
。现在,A
使用A
并在mro中找到super()
,因此它调用了B
__init__()
。接下来,B
的{{1}}再次呼叫__init__()
C
。
在__init__()
中拨打B
会创建一个不同的mro,并避免对super()
的{{1}}进行双重调用。
__init__()
使用:
__init__()
答案 1 :(得分:1)
让我们稍微修改一下代码并将__init__
替换为doit
,以确保该行为是通用的,与__init__
无关。
让我们添加更多输出以查看到底发生了什么:
class A(object):
def doit(self):
print "A", self, super(A, self)
super(A, self).doit()
class B(object):
def doit(self):
print "B", self, super(B, self)
class C(A,B):
def doit(self):
print "C", self
A.doit(self)
B.doit(self)
print "MRO:", [x.__name__ for x in C.__mro__]
#MRO: ['C', 'A', 'B', 'object']
C().doit()
这将输出:
C <__main__.C object at ...>
A <__main__.C object at ...> <super: <class 'A'>, <C object>>
B <__main__.C object at ...> <super: <class 'B'>, <C object>>
B <__main__.C object at ...> <super: <class 'B'>, <C object>>
你知道,self
实际上是C
个对象,所以当你点击A.doit
时,你实际上有<super: <class 'A'>, <C object>>
。
转化为:
对象C
的在MRO列表中的
doit
之后调用下一个(超级)类的A
方法
A
之后,MRO中的下一个班级是B
,因此我们最终会调用B.doit()
。
同时检查此代码:
class C(A,B):
def doit_explain(self):
print "C", self
# calls B.doit()
super(A, self).doit()
print "Back to C"
# calls A.doit() (and super in A also calls B.doit())
super(C, self).doit()
print "Back to C"
# and just B.doit()
B.doit(self)
此处代替A.doit(self)
我直接使用super(A, self).doit()
并且它也会导致B.doit()
调用,这是输出:
C <__main__.C object at ...>
B <__main__.C object at ...> <super: <class 'B'>, <C object>>
Back to C
A <__main__.C object at ...> <super: <class 'A'>, <C object>>
B <__main__.C object at ...> <super: <class 'B'>, <C object>>
Back to C
B <__main__.C object at ...> <super: <class 'B'>, <C object>>