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

Dav*_*ton 13 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
Run Code Online (Sandbox Code Playgroud)

现在,我想使用mixin而不在父级中剔除保存的行为.因此,当我保存时,我想要做C,B和A的东西.我已经读过在混合中调用超级类的setter但是我没有得到它并且已经阅读了它看起来不那么超级文档回答我的问题.

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

Cli*_*ath 14

如何在你的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()
Run Code Online (Sandbox Code Playgroud)

这将为您提供输出:

$ python test.py
parent
mixin
self
Run Code Online (Sandbox Code Playgroud)

  • 令人讨厌的是,大多数IDE会突出显示`MyMixin`的`super(...).test()`调用,因为在技术上没有`MixMixin`上的父类调用`test()`. (5认同)

Vla*_*kov 8

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

在此输入图像描述

以下是如何让您的 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()
Run Code Online (Sandbox Code Playgroud)

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


zvo*_*one 7

从超类调用实现的最佳实践是使用super():

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

重要的是你调用super()每个类(以便它一直传播)但不是最顶层(基类),因为它的超类没有save().

请注意,当您调用时super(Mixin, self).save(),您实际上并不知道超类在执行后会是什么.这将在稍后定义.

与其他语言不同,在python中,结束类将始终具有从中继承的类的线性列表.这称为MRO(方法解决顺序).从MRO Python决定在super()通话时做什么.您可以通过以下方式查看MRO对您的课程的影响:

>>> A.__mro__
(<class '__main__.A'>, <class '__main__.Parent'>, <class '__main__.Model'>, <class '__main__.Mixin'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)

所以,A中超就是Parent,Parent中超就是Model,Model"超级是MixinMixin"超级的object.

那是错的,所以你应该改变A父母:

class A(Mixin, Parent):
Run Code Online (Sandbox Code Playgroud)

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

>>> A.__mro__
(<class '__main__.A'>, <class '__main__.Mixin'>, <class '__main__.Parent'>, <class '__main__.Model'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)