在Python中创建两次Object

时间:2016-02-25 12:10:52

标签: python oop inheritance

我读过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的构造函数

的方式

2 个答案:

答案 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>>