2012-04-05 5 views
6

우선, 더 좋은 제목이 없다는 것에 대해 사과해야합니다. 당신이 더 적절한 것을 찾으면 그것을 자유롭게 바꾸십시오.파이썬 다이아몬드 상속과 파생 클래스의 부모에서 super() 사용

기본적으로 나는 파이썬의 다중 상속 행위에 의해 도청 당했다. 내 previous SO question에서, 나는 Python's C3 MRO을 읽도록 지시 받았다. 파이썬에서 다중 상속을 더 잘 이해할 수있게 도와줍니다. 내가 그것을 이해했다고 생각했을 때, 나는 다음과 같은 시나리오에 부딪혔다. 나는 그것을 이해할 수없는 것처럼 보였다.

class UltimateBase(object): 
    def check(self): 
     print 'base check' 

class AMixin1(UltimateBase): 
    def check(self): 
     print 'check A' 

class BMixin1(UltimateBase): 
    def check(self): 
     print 'check B' 

class CMixin1(UltimateBase): 
    def check(self): 
     print 'check C' 

class AMixin2(UltimateBase): 
    def check(self): 
     print 'check A' 
     return super(AMixin2, self).check() 

class BMixin2(UltimateBase): 
    def check(self): 
     print 'check B' 
     return super(BMixin2, self).check() 

class CMixin2(UltimateBase): 
    def check(self): 
     print 'check C' 
     return super(CMixin2, self).check() 

class MyView1(AMixin1, BMixin1, CMixin1): 
    pass 

class MyView2(AMixin2, BMixin2, CMixin2): 
    pass 

class MyView3(AMixin1, BMixin2, CMixin2): 
    pass 

class MyView4(AMixin2, BMixin1, CMixin2): 
    pass 

class MyView5(AMixin2, BMixin2, CMixin1): 
    pass 

class MyView6(AMixin1, BMixin1, CMixin2): 
    pass 

class MyView7(AMixin1, BMixin2, CMixin1): 
    pass 

class MyView8(AMixin2, BMixin1, CMixin1): 
    pass 

myview1 = MyView1() 
myview2 = MyView2() 
myview3 = MyView3() 
myview4 = MyView4() 
myview5 = MyView5() 
myview6 = MyView6() 
myview7 = MyView7() 
myview8 = MyView8() 

myview1.check() 
print '------------------------' 
myview2.check() 
print '------------------------' 
myview3.check() 
print '------------------------' 
myview4.check() 
print '------------------------' 
myview5.check() 
print '------------------------' 
myview6.check() 
print '------------------------' 
myview7.check() 
print '------------------------' 
myview8.check() 
print '------------------------' 

출력 :

check A 
------------------------ 
check A 
check B 
check C 
base check 
------------------------ 
check A 
------------------------ 
check A 
check B 
------------------------ 
check A 
check B 
check C 
------------------------ 
check A 
------------------------ 
check A 
------------------------ 
check A 
check B 
------------------------ 

내가 출력을 관찰에 기초한 패턴을 추적 할 수 있지만, 버그 나이 결과 뒤에 근거를 이해하지.

나는 예를 들어, 왜 myview2.check() 반환

check A 
check B 
check C 
base check 

을하지 않습니다

check A 
base check 

내가 다중 상속에 대한 중요한 부분을 놓치고 나에게 것 같은 질문이 있습니다. 나를위한 간격을 채우십시오.

답변

4

myview2.check()을 호출하면 형제를 탐색하고 기본 클래스를 호출합니다. 이러한 트래버스 중 하나가 AMixin1, BMixin1 또는 CMixin1이 될 때마다 해당 클래스는 super(..., self).check()을 호출하지 않으므로 중지됩니다.

Benn은 지적했듯이이 내용은 official Python documentation에 설명되어 있습니다. 그리고 그것에 대해 생각한다면,이 방법으로 작동해야합니다. 서브 클래스는 서브 클래스가 super()을 호출하기 전에 기본 클래스 메소드가 호출되지 않는다고 가정합니다. 그것이 (또는 더 나쁜 경우, 형제가 나열된 순서에 따라 다르면) 처리하기가 매우 어렵습니다.

+0

크리스. 이것은 반 직관적입니다. 부모가'super()'를 호출하지 않으면 결과의 모양에서 공통 조상의'check()'가 호출되지 않습니다. 이것에 대해 이야기하는 문헌이 있습니까? – tamakisquare

+1

대체로 같은 것을 말하는 또 다른 답변을 추가하는 대신,이 경우에는 마술을하는'super()'문서를 링크 할 것입니다 : [공식 Python 문서] (http : //docs.python. org/library/functions.html? highlight = super # super). 열쇠는 협동 적 다중 상속을 위해 부모 또는 형제 중 '형'이라고 부를 것입니다. – Benn

+0

@Benn - 정확히 내 문제에 필요한 마지막 부분입니다. 정말 고맙습니다. – tamakisquare

1

같은 질문에 내 머리를 쓰려고했습니다. 다음 코드는 문제를 단순화 도움이 발견 : (. 모든 super의이 클래스에 명중 된 경우 기본적으로 해당 클래스가 호출되는)

class A: 
    def f(self): 
    print("............A: the common base of B and C") 

class B(A): 
    def f(self): 
    print("........B: the left base of D") 
    super().f() 

class C(A): 
    def f(self): 
    print("........C: the right base of D") 
    super().f() 

class D(B,C): 
    def f(self): 
    print("....D: the top class") 
    super().f() 

d = D() 

d.f() 

출력 :

....D: the top class 
........B: the left base of D 
........C: the right base of D 
............A: the common base of B and C 

Try Online

관련 문제