Python mixins:object .__ init __()不带参数

时间:2017-12-25 22:28:18

标签: python python-3.x inheritance mixins

我有一个与Python mixin类有关的问题。这是我的代码:

class Base(object):
    def __init__(self, *args, **kwargs):
        print('Base; {}; {}'.format(args, kwargs))
        super().__init__(*args, **kwargs)


class Mixin1(object):
    def __init__(self, *args, **kwargs):
        print('Mixin1; {}; {}'.format(args, kwargs))
        super().__init__(*args, **kwargs)


class Mixin2(object):
    def __init__(self, *args, **kwargs):
        print('Mixin2; {}; {}'.format(args, kwargs))
        super().__init__(*args, **kwargs)


class C(Mixin1, Mixin2, Base):
    pass

当我致电c = C(arg1=10, arg2=20)时,我收到以下错误:

TypeError: object.__init__() takes no parameters

我理解为什么会收到此错误:Base.__init__()调用super().__init__(*args, **kwargs),即object.__init__()并且不接受任何参数。有没有办法以干净的方式解决这个问题?

一种解决方案是省略*args类中的**kwargsBase,只调用super().__init__()。但如果有人写class C(Base, Mixin2): pass,这就失败了。另一个解决方案是围绕每个try ... except调用的super()子句,这对我来说似乎都不是一个好的解决方案。

有人知道如何处理这个问题吗?提前谢谢!

1 个答案:

答案 0 :(得分:0)

我相信我已经理解了这个问题,我也遇到了同样的问题,我在其中定义了一组混合包,每个混合包都会弹出一些参数,并将其余参数传递给它们的超类。它们可以按任何顺序初始化。

之所以碰到这个错误,是因为我犯了一个完全不同的错误:根本没有定义基类(接受(self, *args, **kwargs)函数签名)。

我(可能是您)想要的是一个Base类,该类:

  • 接受* args和** kwargs,因此您可以使用混合的任意组合
  • 满足@Willem Van Onsem的关注,如果您根本不称呼他们,则论点会悄悄消失。

看起来像这样:


class ResourceBase:
    """ Allows you to use any combination of mixin classes which pass unused *args and **kwargs up to their superclass,
    without encountering:
    ```
    Error
    Traceback (most recent call last):
        super().__init__(*args, **kwargs)
    TypeError: object.__init__() takes no parameters
    ```
    on initialisation.

    The case of passing extra args and kwargs to your class constructor which aren't popped by the various
    mixins is still handled safely with the same error (to prevent loss of variables and poorly defined behaviour
    later).
    """

    def __init__(self, *args, **kwargs):
        """ Constructor for ResourceBase
        """
        if (len(args) > 0) or (len(kwargs.keys()) > 0):
            # Initialisation has gone all the way up to the base class and there are still parameters in *args or **kwargs. Scream at the user (you could probably give a more helpful error message than this)
            raise TypeError('object.__init__() takes no parameters')
        super().__init__()

这允许您以任意顺序创建和使用任意数量的混合签名,其签名如下:


class MyMixin:
    """ Mixin to do a thing with an important kwarg.
    Notice how `my_important_kwarg` is popped out of the kwargs in the constructor signature, so shouldn't end up at the base class.
    """
    def __init__(self, *args, my_important_kwarg=None, **kwargs):
        """ Constructor for MyMixin
        """
    
        super().__init__(*args, **kwargs)

        # Do something with your my_important_kwarg
        self._my_important_kwarg = my_important_kwarg