如何将函数的重写普遍应用于 python 中的多个类?
我正在开发一个 Django 应用程序,但这似乎只是一个 python 问题,没有什么特定于 Django 的。我对 python 还很陌生,很难描述我想要做什么,但更容易展示,所以这里是:
我有一个类:
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 代码中看到的任何问题:))
I am working on a Django application but this seems like it is just a python question, with nothing necessarily specific to Django. I'm pretty new to python, and its hard to describe what I am trying to do, but easier to show so here goes:
I have one class:
class SlideForm(ModelForm):
class Meta:
model = Slide
which I subclass:
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
and then I have another class:
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
which I also sub-class:
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
Note that the subclasses have the exact same code other than class names and do the exact same thing. I have been trying to figure what the best way to genericize this so I can keep it DRY and easily use it for other classes, and have considered decorators and/or multiple inheritance--both of which are new concepts for me--but I keep getting mixed up.
Help is appreciated!
(As a side note, feel free to point out any problems you see in my django code :) )
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种选择是使用 Mixin 类;示例:
首先,mixin 中的常见行为:
只要您能够合理控制继承图中的所有类,并且只要您在每个需要的方法中调用
super
如果要被重写,那么派生类的外观并不重要。但是,当超类之一本身没有在正确的时间调用
super
时,您就会遇到问题。在这种情况下,必须最后调用被重写的方法,这一点非常重要,因为一旦调用它,就不会再进行任何调用。最简单的解决方案是确保每个类实际上都派生自有问题的超类,但在某些情况下,这是不可能的;派生一个新类会创建一个您实际上并不希望存在的新对象!另一个原因可能是因为逻辑基类在继承树上太远而无法计算。 \
在这种情况下,您需要特别注意基类的列出顺序。 Python 将首先考虑最左边的超类,除非继承图中存在更派生的类。这是一个涉及的主题,要了解 python 的真正用途,您应该阅读 C3 MRO 算法出现在 python 2.3 及更高版本中。
基类和以前一样,但由于所有公共代码都来自 mixin,因此派生类变得微不足道。
请注意,mixin 类首先出现,因为我们无法控制
*Form 的内容
类在其 init 方法中执行此操作。如果其中任何一个的 __init__ 方法都非常重要,那么您仍然会获胜。
确保
object
位于继承图中的某个位置。否则可能会发生奇怪的事情。One option is to use a Mixin class; example:
First, the common behavior goes in the mixin:
To the extent that you are in reasonable control of all of the classes in the inheritance graph, and so long as you call
super
in every method that needs to be overridden, then it doesn't matter too much what the derived classes look like.However, you run into a problem when one of the superclasses does not itself call
super
at the correct time. It's very important that the overridden method, in that case, must be called last, since once it's called, no more calls will be made.The simplest solution is to make sure that each class actually derives from the offending superclass, but in some cases, that's just not possible; deriving a new class creates a new object that you don't actually want to exist! Another reason might be because the logical base class is too far up the inheritance tree to work out. \
In that case, you need to pay particular attention to the order in which base classes are listed. Python will consider the left-most superclass first, unless a more derived class is present in the inheritance diagram. This is an involved topic, and to understand what python is really up to, you should read about the C3 MRO algorithm present in python 2.3 and later.
Base classes as before, but since all of the common code comes from the mixin, the derived classes become trivial
Note that the mixin class appears first, since we can't control what the
*Form
classes do in their init methods.If the
__init__
methods of either are non-trivial, you still get a win.Make sure that
object
is in the inheritance diagram, somewhere. Strange things can happen otherwise.多重继承(具体来说,Mixins)可能是最好的解决方案。
示例:
请注意,如果您在两个类中覆盖
__init__
,这可能无法直接起作用。在这种情况下,您可以执行以下操作来指定顺序:Multiple inheritance (specifically, Mixins) would probably be the best solution here.
Example:
Do note that this might not work directly if you overwrite
__init__
in both classes. In that case you could do something like this to specify the order: