python - 如何将一个函数的重写一般地应用于 python 中的多个类?

标签 python django inheritance decorator

我正在开发 Django 应用程序,但这似乎只是一个 Python 问题,不一定是 Django 特有的。我是 python 的新手,很难描述我想做什么,但更容易展示,所以这里是:

我有一个类(class):

class SlideForm(ModelForm):

    class Meta:
        model = Slide

我的子类:

class HiddenSlideForm(SlideForm):
    def __init__(self, *args, **kwargs):
        super(HiddenSlideForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.iteritems():
            field.widget = field.hidden_widget()
            field.required = False

然后我有另一个类:

class DeckForm(ModelForm):     

    def __init__(self, *args, **kwargs):
        # do some stuff here
        return super(DeckForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Deck
        # other stuff here  

我还对其进行了子类:

class HiddenDeckForm(DeckForm):

    def __init__(self, *args, **kwargs):
        super(HiddenDeckForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.iteritems():
            field.widget = field.hidden_widget()
            field.required = False

请注意,除了类名之外,子类具有完全相同的代码并执行完全相同的操作。我一直在试图弄清楚什么是通用化它的最佳方法,这样我就可以保持干燥并轻松地将它用于其他类,并且考虑过装饰器和/或多重继承——这对我来说都是新概念——但我继续混淆。

感谢您的帮助!

(作为旁注,请随时指出您在我的 Django 代码中看到的任何问题 :) )

最佳答案

一种选择是使用 Mixin 类;示例:

首先,mixin 中的常见行为:

class SomeMixin(object):
    def __init__(self, *args, **kwargs):
        super(SomeMixin, self).__init__(*args, **kwargs)
        for name, field in self.fields.iteritems():
            field.widget = field.hidden_widget()
            field.required = False

只要你能合理控制继承图中的所有类,只要你在每个需要重写的方法中调用super,那么它就不会派生类的样子太重要了。

但是,当其中一个父类(super class)本身没有在正确的时间调用 super 时,您就会遇到问题。非常重要的一点是,在这种情况下,必须最后 调用被覆盖的方法,因为一旦调用它,就不会再进行调用。

最简单的解决方案是确保每个类实际上都派生自有问题的父类(super class),但在某些情况下,这是不可能的;派生一个新类会创建一个您实际上不想存在的新对象!另一个原因可能是因为逻辑基类在继承树上太远而无法计算。\

在这种情况下,您需要特别注意列出基类的顺序。 Python 将首先考虑最左边的父类(super class),除非继承图中存在更派生的类。这是一个涉及的话题,要了解 python 的真正用途,您应该阅读 C3 MRO algorithm存在于 python 2.3 及更高版本中。

基类和以前一样,但是由于所有公共(public)代码都来自混合,派生类变得微不足道

class HiddenSlideForm(SomeMixin, SlideForm):
    pass

class HiddenDeckForm(SomeMixin, DeckForm):
    pass

请注意,mixin 类出现在第一个,因为我们无法控制*Form 类在它们的init 方法中执行的操作。

如果其中任何一个的 __init__ 方法都非常重要,您仍然会赢。

class HiddenSlideForm(SomeMixin, SlideForm):
    def __init__(self, *args, **kwargs):
        super(HiddenSlideForm, self).__init__(*args, **kwargs)
        do_something_special()

确保 object 在继承图中的某处。否则可能会发生奇怪的事情。

关于python - 如何将一个函数的重写一般地应用于 python 中的多个类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6052710/

相关文章:

python - S3 PutObject 无提示故障?

python - 运行 subprocess.call 来运行 Cocoa 命令行应用程序

django - 有没有办法在不通过电子邮件发送重置链接的情况下使用 Django 的默认密码重置?

java - 为什么 protected 变量在类级别可见?

java - 将方法添加到内置类

python - Python中的uWSGI请求超时

javascript - Nodejs 查找已知蓝牙设备

html - 关于for循环(循环模板)

python - 绕过 pip 卸载的确认提示

c++ - 为什么此代码会引发 LNK2019 错误?