31

Powiedz, mam następujące wstawek, które pokrywa się ze sobą poprzez dotknięcie dispatch():Jak kolejność mixinów wpływa na klasę pochodną?

class FooMixin(object): 
    def dispatch(self, *args, **kwargs): 
     # perform check A 
     ... 
     return super(FooMixin, self).dispatch(*args, **kwargs) 

class BarMixin(object): 
    def dispatch(self, *args, **kwargs): 
     # perform check B 
     ... 
     return super(FooMixin, self).dispatch(*args, **kwargs) 

Jeśli chcę mój pogląd, aby przejść przez kolejności sprawdzić, A -> sprawdzić B, powinny mój kod będzie MyView(FooMixin, BarMixin, View) lub MyView(BarMixin, FooMixin, View) ?

A dlaczego zawsze wstawiamy View lub jego podklasy po mixins? (Zauważyłem to po przeczytaniu kodu źródłowego generycznych widoków django, ale nie znam racjonalnego uzasadnienia, jeśli takie istnieją).

Odpowiedz

57

MRO to w zasadzie głębia-pierwsza, od lewej do prawej. Zobacz Method Resolution Order (MRO) in new style Python classes, aby uzyskać więcej informacji.

Możesz sprawdzić, czy klasa __mro__ attribute sprawdza, ale FooMixin powinna być pierwsza, jeśli chcesz najpierw wykonać "sprawdzenie".

class UltimateBase(object): 
    def dispatch(self, *args, **kwargs): 
     print 'base dispatch' 

class FooMixin(object): 
    def dispatch(self, *args, **kwargs): 
     print 'perform check A' 
     return super(FooMixin, self).dispatch(*args, **kwargs) 

class BarMixin(object): 
    def dispatch(self, *args, **kwargs): 
     print 'perform check B' 
     return super(BarMixin, self).dispatch(*args, **kwargs) 

class FooBar(FooMixin, BarMixin, UltimateBase): 
    pass 

FooBar().dispatch() 

Wydruki:

perform check A 
perform check B 
base dispatch 

View musi być ostatni tak, że „łapie” wszelkie wyszukiwań atrybutów, które nie były na żadnych wstawek, bez ukrywania jakichkolwiek metod na tych wstawek. Nie jestem pewien, czy rozumiem tę część twojego pytania - co to jest "dlaczego jest w ogóle dodane" lub "dlaczego jest dodane jako ostatnie"?

+1

thx agf. Moje pytanie miało być "dlaczego jest dodane do ostatniego" i odpowiedziałeś na nie. Twoje zdrowie. – tamakisquare

+1

Dla jasności jedyną metodą, która bezpośrednio wywołuje, jest 'FooMixin.dispatch'. 'super (FooMixin, self) .dispatch' następnie przechodzi do' BarMixin.dispatch', ponieważ 'object' nie ma metody" dispatch ". 'super (BarMixin, self) .dispatch' ma wartość' UltimateBase.dispatch' z tego samego powodu. –

+0

@MadPhysicist To nie w porządku. To zadziała, nawet jeśli metoda jest również zdefiniowana przez obiekt - spróbuj sam. Zobacz połączoną odpowiedź, aby uzyskać więcej informacji. – agf

Powiązane problemy