Mixin 类 __init__ 函数不会自动调用吗?

新手上路,请多包涵

我想使用 Mixin 始终向我的子类添加一些初始化功能,每个子类都继承自不同的 API 基类。具体来说,我想制作多个不同的子类,它们继承自这些不同的 API 提供的基类之一和一个 Mixin,它们将始终以相同的方式执行 Mixin 初始化代码,而无需代码复制。但是,似乎 Mixin 类的 init 函数永远不会被调用,除非我在 Child 类的 init 函数中明确调用它,这不太理想。我建立了一个简单的测试用例:

 class APIBaseClassOne(object):
    def __init__(self, *args, **kwargs):
        print (" base ")

class SomeMixin(object):
    def __init__(self, *args, **kwargs):
        print (" mixin before ")
        super(SomeMixin, self).__init__(*args, **kwargs)
        print (" mixin after ")

class MyClass(APIBaseClassOne):
    pass

class MixedClass(MyClass, SomeMixin):
    pass

正如您在以下输出中看到的,Mixin 函数的 init 永远不会被调用:

 >>> import test
>>> test.MixedClass()
 base
<test.MixedClass object at 0x1004cc850>

有没有办法做到这一点(在 Mixin 中调用一个 init 函数)而不用编写每个子类来显式调用 Mixin 的 init 函数? (即,不必在每个班级都做这样的事情:)

 class MixedClass(MyClass, SomeMixin):
    def __init__(*args, **kwargs):
        SomeMixin.__init__(self, *args, **kwargs)
        MyClass.__init__(self, *args, **kwargs)

顺便说一句,如果我所有的子类都继承自同一个基类,我意识到我可以创建一个新的中间类,它继承自基类和混合类,并以这种方式保持干燥。但是,它们继承自具有共同功能的不同基类。 (Django Field 类,准确地说)。

原文由 B Robster 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 876
2 个回答

对不起,我这么晚才看到这个,但是

class MixedClass2(SomeMixin, MyClass):
    pass

>>> m = MixedClass2()
 mixin before
 base
 mixin after

@Ignacio 正在谈论的模式称为合作多重继承,它很棒。但是如果一个基类对合作不感兴趣,就把它作为第二个基类,把你的 mixin 作为第一个。在 Python 的 MRO 之后,mixin 的 __init__() (以及它定义的任何其他内容)将在基类之前被检查。

这应该可以解决一般问题,但我不确定它是否可以处理您的特定用途。具有自定义元类(如 Django 模型)或具有奇怪装饰器(如@martineau 的回答;)的基类可以做一些疯狂的事情。

原文由 Matt Luongo 发布,翻译遵循 CC BY-SA 3.0 许可协议

让基类调用 super().__init__() 即使它是 object 的子类。这样所有的 __init__() 方法都会运行。

 class BaseClassOne(object):
    def __init__(self, *args, **kwargs):
        super(BaseClassOne, self).__init__(*args, **kwargs)
        print (" base ")

原文由 Ignacio Vazquez-Abrams 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题