4

super()多重継承のコンテキストでの動作を理解しようとしています。super()test2.py の親クラスでの呼び出しが両方の親に対して呼び出される理由について混乱してい__init__()ますか?

test1.py

#!/usr/bin/env python

class A(object):

    def __init__(self):
        self.A = "A"
        print self.A

class B(object):

    def __init__(self):
        self.B = "B"
        print self.B

class C(A, B):

    def __init__(self):
        self.C = "C"
        print self.C
        super(C, self).__init__()

if __name__ == '__main__':
    print "Without super() in parent __init__():"
    c = C()
    print c.__dict__
    print C.__mro__

生成:

$ ./test.py 
Without super() in parent __init__():
C
A
{'A': 'A', 'C': 'C'}
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)

test2.py

#!/usr/bin/env python

class A(object):

    def __init__(self):
        self.A = "A"
        print self.A
        super(A, self).__init__()

class B(object):

    def __init__(self):
        self.B = "B"
        print self.B
        super(B, self).__init__()

class C(A, B):

    def __init__(self):
        self.C = "C"
        print self.C
        super(C, self).__init__()

if __name__ == '__main__':
    print "With super() in parent __init__():"
    c = C()
    print c.__dict__
    print C.__mro__

生成:

$ ./test2.py 
With super() in parent __init__():
C
A
B
{'A': 'A', 'C': 'C', 'B': 'B'}
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)
4

1 に答える 1

6

あなたの間違いはあなたのコメントにあります:

super(C, self).__init__()  <-- call to object.__init__()

これは への呼び出しではありませんobject.__init__。クラス C とインスタンスの両方を渡す理由は、クラスのスーパークラスだけでなく、インスタンスの MRO に基づいて、次に何を呼び出すかを知るためですselfsuper本質的には、「自分の MRO で C の後にクラスsuper(C, self).__init__の を呼び出す」ことを意味します。__init__

これが要点です---クラス定義時にどのクラスであるかを知る必要なく、クラスが「MRO の次のクラスに制御を渡す」ことを意味するsuperように呼び出すことができる協調継承を可能にします。super

A は MRO の C の次のクラスであるためsuper(C, self).__init__、 を呼び出すと、 が呼び出されます。A.__init__次に、A が を呼び出すとsuper(A, self).__init__、それが を呼び出しますB.__init__。なぜなら、B は MRO の A の後のクラスだからです。

(スーパークラスメソッドを呼び出した後に各メッセージを出力するため、メッセージは逆の順序で出力されることに注意してください--- B、A、C --- B.__init__。その後、継承ツリーを下る途中で他のメッセージが出力されます。)

于 2013-06-24T06:37:25.467 に答える