2016-12-28 4 views
1

を呼び出します。私はこののpython多重継承、私はPythonで多重継承で何かをしようとしていた基底クラスの関数

class ParentOne: 
    def foo(self): 
     print("ParentOne foo is called") 

class ParentTwo: 
    def foo(self): 
     print("ParentTwo foo is called") 

class Child(ParentOne, ParentTwo): 

    # how is this working 
    def call_parent_two_foo(self): 
     super(ParentOne, self).foo() 

    # This does not work 
    def call_parent_foo(self): 
     super(ParentTwo, self).foo() 

    def call_super_foo(self): 
     super(Child, self).foo() 

    def foo(self): 
     print("Child foo is called") 


if __name__ == "__main__": 
    child = Child() 
    child.foo() 
    child.call_super_foo() 
    child.call_parent_two_foo() 

    # child.call_parent_foo() #This gives the below error 
    # super(ParentTwo, self).foo() 
    # AttributeError: 'super' object has no attribute 'foo' 

を思い付く、それは私がsuper(ParentOne, self).foo()の呼び出しは、このケースで評価され、どのようにと混乱しています次の出力

Child foo is called 
ParentOne foo is called 
ParentTwo foo is called 

を与えます。私の理解あたりとしてParentOneクラスはParentTwoクラスのメソッドと属性の任意のアイデアを持っていません。多重継承の場合には、スーパー作品をどのよう

答えて

3

Pythonはそれがクラスを構築するメソッド解決順序(MRO)を構築します。 MROはです。常に linearです。 Pythonが線形MROを作成できない場合は、ValueErrorが生成されます。この場合、あなたのMROは、おそらく次のようになります。Pythonはsuper(cls, self)だ見たときに

Child -> ParentOne -> ParentTwo -> object 

さて、それは基本的にselfを見て、MROを割り出し。その後、我々はMROにおける現在の位置は、最終的にそれがMROにクラスに委任するオブジェクトを返す場所を決定するためにclsを使用しています。したがって、この場合、super(Child, self)呼び出しはParentOneに委譲するオブジェクトを返します。 super(ParentOne, self)クラスは、ParentTwoに委譲するオブジェクトを返します。最後にsuper(ParentTwo, self)コールはobjectに委任されます。 super(ParentTwo, self)objectに「委任」を返すので、あなたがしようとしたときにAttributeErrorを取得している理由は、我々が見ることができることを

def kinda_super(cls, self): 
    mro = inspect.getmro(type(self)) 
    idx = mro.index(cls) 
    return Delegate(mro[idx + 1]) # for a suitably defined `Delegate` 

注:つまり、あなたは、次のコードの手の込んだバージョンとしてsuperと考えることができますsuper(ParentTwo, self).foo()からobjectは何fooメソッドを持っていないので、具体的に理由があります。

+0

はMRO –

+0

@AnuragSharma取得/見るために彼らの方法です。 IIRCでは、魔法の '__mro__'属性でアクセスすることもできます。 – mgilson

0

あなたは、チェーン内Child(ParentOne, ParentTwo) 2などの別々の継承を理解することがあります。Child(ParentOne(ParentTwo))。実際にはParentOneParentTwoを継承しませんが、2つの別々のクラスですが、superというメソッドは継承の連鎖(複数の継承の場合のみ)のように機能します。私は(Pythonの3.xのために)何が起こっているかをよりよく理解するために、この例のように:

class P: 
    def m(self): 
     print("P") 


class A(P): 
    def m(self): 
     super().m() # -> B, if we inherit like C(A, B) 
     print("A") 


class B(P): 
    def m(self): 
     super().m() # -> P, if we inherit like C(A, B) 
     print("B") 


class C(A, B): 
    def m(self): 
     super().m() # -> A 
     print("C") 
     A.m(self) 
     B.m(self) 


c = C() 
c.m() 

2人の親が一つのベースクラスを継承する場合、それはまた、場合を考えます。印刷物上のスクリプト: - `inspect.getmro`はあなたにそれを与える必要があります

P 
B 
A 
C 
P 
B 
A 
P 
B