2013-12-08 4 views
10

Итак, у меня такая ситуация.Python Call Parent Method Multiple Inheritance

class A(object): 
    def foo(self, call_from): 
     print "foo from A, call from %s" % call_from 


class B(object): 
    def foo(self, call_from): 
     print "foo from B, call from %s" % call_from 


class C(object): 
    def foo(self, call_from): 
     print "foo from C, call from %s" % call_from 


class D(A, B, C): 
    def foo(self): 
     print "foo from D" 
     super(D, self).foo("D") 

d = D() 
d.foo() 

Результат кода

foo from D 
foo from A, call from D 

Я хочу призвать все родительский метод, в данном случае, метод Foo из D класса без использования супер в родительском классе как A. Я просто хочу назвать супер из класса D. Класс A, B и C - это как класс mixin, и я хочу назвать все методы foo от D. Как я могу достичь этого?

ответ

7

Вы можете использовать __bases__ как этот

class D(A, B, C): 
    def foo(self): 
     print "foo from D" 
     for cls in D.__bases__: 
      cls().foo("D") 

С этим изменением, то выход будет

foo from D 
foo from A, call from D 
foo from B, call from D 
foo from C, call from D 
+0

Это немного отрывочно ... Что делать, если у вас теперь есть два класса, которые наследуются от D, а затем еще один класс, который наследуется от обоих? Теперь 'foo' дважды вызовет' A.foo'. – mgilson

+1

Или что происходит, если 'B.foo' не существует? И, наконец, я думаю, что это должно быть 'cls.foo (self)', а не 'cls(). Foo()' – mgilson

+0

@mgilson. Тогда мы должны использовать 'mro'? И это не классные методы, верно? Итак, мне пришлось создавать объекты, чтобы их вызвать. – thefourtheye

8

Добавить super() calls в других классах, кроме C. Поскольку двойки MRO является

>>> D.__mro__ 
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>) 

Вам не нужно супер вызов в C.

Код:

class A(object): 
    def foo(self, call_from): 
     print "foo from A, call from %s" % call_from 
     super(A,self).foo('A') 

class B(object): 
    def foo(self, call_from): 
     print "foo from B, call from %s" % call_from 
     super(B, self).foo('B') 


class C(object): 
    def foo(self, call_from): 
     print "foo from C, call from %s" % call_from 

class D(A, B, C): 
    def foo(self): 
     print "foo from D" 
     super(D, self).foo("D") 

d = D() 
d.foo() 

Выход:

foo from D 
foo from A, call from D 
foo from B, call from A 
foo from C, call from B 
+0

Если вы не понимаете моего описания, я хочу вызвать весь метод 'foo', не вызывая super в родительском классе, например' A' или 'B' или' C'. –

+1

@EdwinLunando - Я считаю, что это просто не так. Для того, чтобы super работал правильно, все классы должны использовать его. [см. раздел о методах смешивания супер методов с не супер методами] (https://fuhm.net/super-harmful/). – mgilson

+0

@EdwinLunando Затем перебирайте '__mro__' или' __bases__' и вызывайте каждый класс явно, но тогда вы ** не можете использовать ** 'super' в' D'. –