如何在Python中的mixin中调用封闭类的超级?

时间:2016-09-08 16:04:41

标签: python

我在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

现在,我想使用mixin而不会在Parent中剔除保存行为。因此,当我保存时,我想要做C,B和A的东西。我已经读过Calling the setter of a super class in a mixin但是我没有得到它并且阅读了超级文档它似乎没有回答我的问题。

问题是,我应该在mixin中添加什么来确保它能够完成B并且不会阻止Stuff A发生?

4 个答案:

答案 0 :(得分:8)

如何在mixin课程中调用super?

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 :(得分:5)

从超类调用实现的最佳做法是使用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的超级是ParentParent的超级是ModelModel的超级是MixinMixin的超级是object

这是错误的,所以你应该将A的父母改为:

class A(Mixin, Parent):

然后你会有一个更好的MRO:

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

答案 2 :(得分:1)

@Click2Death 答案是正确的,但是,当您在 mixin 类中调用 super().test() 时,大多数 IDE 会声称 test 未解析,这是正确的。

enter image description here

这里是如何让您的 IDE 满意并让您的代码更好。

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


class MyMixin(object):
    def test(self):
        super_test = getattr(super(), 'test')
        if super_test and callable(super_test):
            super_test()
        print("mixin")


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

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

这是 Python 3 代码,要使其与 Python 2 一起使用,您需要将两个参数传递给 super(MyClass, self) 调用

答案 3 :(得分:0)

Django 示例(Python 3+)

为了在 Django 上下文中扩展 Vladimir Prudnikov's answer,模板视图 mixin 类的结构可以如下所示。

Microsoft.CSharp