Mixin 类 __init__ 函数不会自动调用吗? [英] Are Mixin class __init__ functions not automatically called?

查看:34
本文介绍了Mixin 类 __init__ 函数不会自动调用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

class APIBaseClassOne(object):def __init__(self, *args, **kwargs):打印(基地")类SomeMixin(对象):def __init__(self, *args, **kwargs):打印(混合前")super(SomeMixin, self).__init__(*args, **kwargs)打印(混合后")类 MyClass(APIBaseClassOne):经过类 MixedClass(MyClass, SomeMixin):经过

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

<预><代码>>>>进口测试>>>test.MixedClass()根据<test.MixedClass 对象在 0x1004cc850>

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

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

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

解决方案

抱歉这么晚才看到,但是

class MixedClass2(SomeMixin, MyClass):经过>>>m = MixedClass2()之前混入根据混合之后

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

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

I'd like to use a Mixin to always add some init functionality to my child classes which each inherit from different API base classes. Specifically, I'd like to make multiple different child classes that inherit from one of these different API-supplied base classes and the one Mixin, which will always have the Mixin initialization code executed in the same way, without code replication. However, it seems that the __init__ function of the Mixin class never gets called unless I explicitly call it in the Child class's __init__ function, which is less than ideal. I've built up a simple test case:

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

As you can see in the following output, the Mixin function's init never gets called:

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

Is there a way to do this (have an init function in a Mixin get called) without writing every child class to explicitly invoke the Mixin's init function? (i.e., without having to do something like this in every class:)

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

Btw, if all my child classes were inheriting from same base class, I realize I could create a new middle class that inherits from the base class and the mixin and keep it DRY that way. However, they inherit from different base classes with common functionality. (Django Field classes, to be precise).

解决方案

Sorry I saw this so late, but

class MixedClass2(SomeMixin, MyClass):
    pass

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

The pattern @Ignacio is talking about is called cooperative multiple inheritance, and it's great. But if a base class isn't interested in cooperating, make it the second base, and your mixin the first. The mixin's __init__() (and anything else it defines) will be checked before the base class, following Python's MRO.

This should solve the general question, though I'm not sure it handles your specific use. Base classes with custom metaclasses (like Django models) or with strange decorators (like @martineau's answer ;) can do crazy things.

这篇关于Mixin 类 __init__ 函数不会自动调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆