Python Mixins:*args/**kwargs 与显式调用 `__init__`

Python Mixins: *args/**kwargs vs explicit call to `__init__`

我尝试使用 ClickableRectangle classes 编写一个混合示例,它们是 Button [=] 的超级classes 25=].

目前我使用:

class Clickable:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.clicks = 0

    def click(self):
        self.clicks = self.clicks + 1


class Rectangle:
    def __init__(self, x0, y0, x1, y1, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.upper_right = (x0, y0)
        self.lower_down = (x1, y1)


class Button(Clickable, Rectangle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

但我考虑使用:

class Clickable:
    def __init__(self):
        self.clicks = 0

    def click(self):
        self.clicks = self.clicks + 1


class Rectangle:
    def __init__(self, x0, y0, x1, y1):
        self.upper_right = (x0, y0)
        self.lower_down = (x1, y1)


class Button(Clickable, Rectangle):
    def __init__(self, x0, y0, x1, y1):
        Rectangle.__init__(self, x0, y0, x1, y1)
        Clickable.__init__(self)

出于某种原因其中之一更好吗?

推荐的方法(参见 https://rhettinger.wordpress.com/2011/05/26/super-considered-super/)是使用关键字参数来避免期望传递哪个父级和哪个位置参数之间的冲突。

class Clickable:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.clicks = 0

    def click(self):
        self.clicks = self.clicks + 1


class Rectangle:
    def __init__(self, x0, y0, x1, y1, **kwargs):
        super().__init__(**kwargs)
        self.upper_right = (x0, y0)
        self.lower_down = (x1, y1)


class Button(Clickable, Rectangle):
    # No need to override __init__ if all it does
    # is pass all its arguments to the next invocation
    pass


b = Button(x0=0, y0=0, x1=10, y1=10)

记住,接受任意关键字参数并首先传递它们的原因是你不知道 class super() 会产生什么,所以你无法预测预期的签名。

根据定义,Mixin 几乎预期会支持协作继承,因为它们预期会与多重继承一起使用,并且某人 可能希望在 class 确实如此。