2016-09-08 2 views
3

У меня есть следующий код, в Django:Как назвать супер вмещающего класса в mixin в Python?

class Parent(models.Model): 
    def save(self): 
     # Do Stuff A 

class Mixin(object): 
    def save(self): 
     # Do Stuff B 

class A(Parent, Mixin): 
    def save(self): 
     super(A, self).save() 
     # Do stuff C 

Теперь я хочу использовать подмешать без blatting поведения сохранить в Parent. Поэтому я, когда я сохраняю, хочу делать вещи C, B и A. Я читал Calling the setter of a super class in a mixin, однако я не понимаю и, прочитав супер-документы, похоже, не отвечает на мой вопрос.

Вопрос в том, что я помещаю в миксин, чтобы убедиться, что он делает материал B и не останавливает материал A?

+0

Вы уверены, что порядок наследования прав - вы обычно положить подмешать * после * родитель ... –

+0

Я не конечно, нет. Я понимаю, что если бы я сделал это наоборот, метод сохранения mixin был бы переопределен Parent. Это верно? –

+0

Нет - MRO (для наложения не алмазов) - справа налево ... –

ответ

4

Как насчет вызова супер в своем классе подмешать?

class Parent(object): 
    def test(self): 
     print("parent") 


class MyMixin(object): 
    def test(self): 
     super(MyMixin, self).test() 
     print("mixin") 


class MyClass(MyMixin, Parent): 
    def test(self): 
     super(MyClass, self).test() 
     print("self") 

if __name__ == "__main__": 
    my_obj = MyClass() 
    my_obj.test() 

Это даст вам выход как:

$ python test.py 
parent 
mixin 
self 
+1

Что очень раздражает, так это то, что большинство IDE выделяют вызов 'super (...). test()' MyMixin', потому что на 'MixMixin' нет стандартного класса для вызова' test() ' на. – jlh

+0

@jlh Я полностью понимаю это, так что я не хочу иметь эту зеленую галочку на инспекторе кода. – Click2Death

4

Лучшая практика для вызова реализации от суперкласса является использование super():

class Mixin(object): 
    def save(self): 
     super(Mixin, self).save() 
     # Do Stuff B here or before super call, as you wish 

Что важно то, что вы называете super() в каждом классе (так, что он распространяется весь путь), но не самый верхний (базового) класса, поскольку его суперкласс не имеет save().

Обратите внимание, что когда вы вызываете super(Mixin, self).save(), вы действительно не знаете, каким будет суперкласс после его выполнения. Это будет определено позже.

В отличие от некоторых других языков, в python, у конечного класса всегда будет линейный список классов, из которых он наследуется. Это называется MRO (Method Resolution Order). От MRO Python решает, что делать по вызову super(). Вы можете увидеть, что MRO для вашего класса так:

>>> A.__mro__ 
(<class '__main__.A'>, <class '__main__.Parent'>, <class '__main__.Model'>, <class '__main__.Mixin'>, <type 'object'>) 

Так, A «супер s является Parent, Parent» супер s является Model, Model «супер s является Mixin и Mixin» супер s является object.

Это неправильно, так что вы должны изменить A «S родителей:

class A(Mixin, Parent): 

Тогда вы бы лучше MRO:

>>> A.__mro__ 
(<class '__main__.A'>, <class '__main__.Mixin'>, <class '__main__.Parent'>, <class '__main__.Model'>, <type 'object'>)