I have the following code, in Django:
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
Now, I want to use the mixin without blatting the behaviour of the save in Parent. So I when I save, I want to do stuff C, B, and A. I've read Calling the setter of a super class in a mixin however I don't get it and having read the super docs it doesn't seem to answer my question.
THe question is, what do I put in the mixin to make sure it does stuff B and doesn't stop Stuff A from happening?
Using Super(): Python super() function provides us the facility to refer to the parent class explicitly. It is basically useful where we have to call superclass functions. It returns the proxy object that allows us to refer parent class by 'super'.
The answer is, the mixin method completely overwrites the original method.
Mixins are an alternative class design pattern that avoids both single-inheritance class fragmentation and multiple-inheritance diamond dependencies. A mixin is a class that defines and implements a single, well-defined feature. Subclasses that inherit from the mixin inherit this feature—and nothing else.
It's perfectly valid for a mixin to inherit from another mixin - in fact, this is how most of Django's more advanced mixins are made. However, the idea of mixins is that they are reusable parts that, together with other classes, build a complete, usable class.
How about calling super in your mixin class?
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()
This will give you the output as:
$ python test.py parent mixin self
The best practice for calling the implementation from the superclass is to use super()
:
class Mixin(object): def save(self): super(Mixin, self).save() # Do Stuff B here or before super call, as you wish
What is important is that you call super()
in each class (so that it propagates all the way) but not the topmost (base) class, because its superclass does not have save()
.
Note that when you call super(Mixin, self).save()
, you don't really know what the super class would be once it is executed. That will be defined later.
Unlike some other languages, in python, the end class will always have a linear list of classes from which it inherits. That is called MRO (Method Resolution Order). From MRO Python decides what to do on super()
call. You can see what the MRO is for your class this way:
>>> A.__mro__ (<class '__main__.A'>, <class '__main__.Parent'>, <class '__main__.Model'>, <class '__main__.Mixin'>, <type 'object'>)
So, A
's super is Parent
, Parent
's super is Model
, Model
's super is Mixin
and Mixin
's super is object
.
That is wrong, so you should change A
's parents to:
class A(Mixin, Parent):
Then you'd have a better MRO:
>>> A.__mro__ (<class '__main__.A'>, <class '__main__.Mixin'>, <class '__main__.Parent'>, <class '__main__.Model'>, <type 'object'>)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With