2015-07-05 31 views
19

Ich arbeite mit etwas Code, der 3 Ebenen der Klassenvererbung hat. Von der abgeleiteten Klasse auf der niedrigsten Ebene, was ist die Syntax zum Aufrufen einer Methode 2 Ebenen die Hierarchie, z. ein super.super Anruf? Die "mittlere" Klasse implementiert nicht die Methode, die ich aufrufen muss.So rufen Sie die Supermethode auf?

+7

Warum brauchen Sie das? Ein einziger 'super()' Aufruf sollte ausreichen, außer Sie haben die Methode in der Mittelklasse überschrieben. In diesem Fall sollte sich die Mittelklasse darum kümmern, die Methode von super() richtig zu benutzen. –

+1

Wenn die Mittelklasse diese Methode nicht implementiert, rufen Sie einfach 'super() auf. () 'sollte es funktionieren, weil durch die Vererbung Ihre Mittelklasse die Methoden von der Superklasse erben würde –

+0

Meinst du, du willst eine Implementierung im MRO * überspringen *? – jonrsharpe

Antwort

34

Nun, das ist eine Möglichkeit, es zu tun:

class Grandparent(object): 
    def my_method(self): 
     print "Grandparent" 

class Parent(Grandparent): 
    def my_method(self): 
     print "Parent" 

class Child(Parent): 
    def my_method(self): 
     print "Hello Grandparent" 
     Grandparent.my_method(self) 

Vielleicht nicht das, was Sie wollen, aber es ist die beste Python hat, wenn ich nicht irre. Was du fragst, klingt antipythonisch und du müsstest erklären, warum du es für uns machst, um dir die glückliche Python-Art zu geben, Dinge zu tun.

Ein weiteres Beispiel vielleicht, was Sie (aus Ihren Kommentaren) wollen:

class Grandparent(object): 
    def my_method(self): 
     print "Grandparent" 

class Parent(Grandparent): 
    def some_other_method(self): 
     print "Parent" 

class Child(Parent): 
    def my_method(self): 
     print "Hello Grandparent" 
     super(Child, self).my_method() 

Wie Sie sehen können, Parent nicht my_method nicht implementiert, aber Child noch Super kann bei dem Verfahren zu erhalten, die Parent „sieht ", dh Grandparent 's my_method.

+0

Ich glaube nicht, dass Sie verschachtelte "Super" -Aufrufe trotzdem tun können, weil der Typ "Super" wäre. –

+0

In meinem Fall implementiert die Parent-Klasse my_method nicht, und ich möchte sie nicht hinzufügen, nur um den untergeordneten Aufruf zum Funktionieren zu bringen. – SeanLabs

+3

Sie müssen nicht, mittlere Klasse erbt Methoden von Elternklassen, also würde 'super(). Method()' funktionieren. –

-2

Wenn Sie zwei Ebenen sichern möchten, warum nicht einfach tun

class GrandParent(object):              

    def act(self):                
     print 'grandpa act'              

class Parent(GrandParent):              

    def act(self):                
     print 'parent act'              

class Child(Parent):                

    def act(self):                
     super(Child.__bases__[0], self).act()          
     print 'child act'               


instance = Child()                
instance.act() 

# Prints out 
# >>> grandpa act 
# >>> child act  

Sie können die Überprüfung etwas defensiver hinzufügen wie wenn __bases__ leer ist oder Schleifen über sie, wenn Ihr Bürgertums Mehrfachvererbung haben. Das Verschachteln von Super funktioniert nicht, da der Super-Typ nicht der übergeordnete Typ ist.

+0

Niemals, * jemals *, benutze 'self .__ class__' in' super() '. Nicht einmal um an die Basen zu kommen. 'self .__ class__' ist ** nicht immer die Klasse, für die Sie die Methode ** definiert haben, es könnte eine Unterklasse sein. Wenn Sie zwei weitere Vererbungsebenen hinzufügen, haben Sie jetzt eine Endlosschleife. –

-1

In Ihrem Fall, wie my_method Funktion der Klasse C von A aufrufen.

Sie können dies auf zwei Arten statisch und dynamisch tun.

dynamisch

class C(object): 
    def my_method(self): 
     print "in function c" 

class B(C): 
    def my_method(self): 
     print "in function b" 

class A(B): 
    def my_method(self): 
     # Call my_method from B 
     super(A, self).my_method() 
     # This is how you can call my_method from C here ? 
     super((self.__class__.__bases__)[0], self).my_method() 
obj_a = A() 
obj_a.my_method() 

Hier (self.__class__.__bases__) werden Basisklassen von A in Tupel Typ das ist zurückgeben, warum ich den 0-ten Index nahm. So gibt es die Klasse B so B Klasse als ein Argument in Super zurückgegeben wird my_method Funktion der Basisklasse von B Klasse.

Statisch

class C(object): 
    def my_method(self): 
     print "in function c" 

class B(C): 
    def my_method(self): 
     print "in function b" 

class A(B): 
    def my_method(self): 
     # Call my_method from B 
     super(A, self).my_method() 
     # This is how you can call my_method from C here ? 
obj_a = A() 
super(A, obj_a).my_method() # calls function of class B 
super(B, obj_a).my_method() # calls function of class C 
+1

Niemals, * jemals *, benutze 'self .__ class__' in' super() '. Nicht einmal um an die Basen zu kommen. 'self .__ class__' ist ** nicht immer die Klasse, für die Sie die Methode ** definiert haben, es könnte eine Unterklasse sein. Wenn Sie zwei weitere Vererbungsebenen hinzufügen, haben Sie jetzt eine Endlosschleife. –

+1

ein bisschen melodramatisch sind wir? – dopatraman

2

Dies funktioniert für mich:

class Grandparent(object): 
    def my_method(self): 
     print "Grandparent" 

class Parent(Grandparent): 
    def my_method(self): 
     print "Parent" 

class Child(Parent): 
    def my_method(self): 
     print "Hello Grandparent" 
     super(Parent, self).my_method() 
+0

Dies ist wahrscheinlich die Antwort, die als die richtige Antwort markiert werden muss – nesdis

Verwandte Themen