[英]How to call super of enclosing class in a mixin in 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。 因此,当我保存时,我想做 C、B 和 A 的事情。我已经阅读了在 mixin 中调用超类的 setter但是我不明白并且阅读了超级文档似乎没有回答我的问题。
问题是,我在 mixin 中放了什么来确保它执行 B 并且不会阻止 A 发生?
在你的 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
从超类调用实现的最佳实践是使用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(方法解析顺序)。 从 MRO Python 决定在super()
调用上做什么。 您可以通过这种方式查看 MRO 对您的班级的意义:
>>> A.__mro__
(<class '__main__.A'>, <class '__main__.Parent'>, <class '__main__.Model'>, <class '__main__.Mixin'>, <type 'object'>)
所以, A
的 super 是Parent
, Parent
的 super 是Model
, Model
的 super 是Mixin
, Mixin
的 super 是object
。
这是错误的,因此您应该将A
的父母更改为:
class A(Mixin, Parent):
那么你会有一个更好的 MRO:
>>> A.__mro__
(<class '__main__.A'>, <class '__main__.Mixin'>, <class '__main__.Parent'>, <class '__main__.Model'>, <type 'object'>)
@Click2Death 答案是正确的,但是,当您在 mixin 类中调用super().test()
大多数 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()
这是 Python 3 代码,要使其与 Python 2 一起使用,您需要将两个参数传递给super(MyClass, self)
调用
为了在 Django 上下文中扩展Vladimir Prudnikov 的回答,模板视图 mixin 类的结构可以如下所示。
from django.views.generic.base import View
class MyViewMixin:
def dispatch(self, request, *args, **kwargs):
super_dispatch = getattr(super(), 'dispatch')
if super_dispatch and callable(super_dispatch):
return super_dispatch(request, *args, **kwargs)
raise RuntimeError('MyViewMixin must be used as part of a '
'multiple inheritance chain that includes a Django template-view')
class MyCustomView(MyViewMixin, View):
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.