在 parent class 中调用 `super()`

Calling `super()` in parent class

我正在阅读 Raymond Hettinger 的 Python’s super() considered super! 关于其中的一个页面,有这个例子:

class Shape:
    def __init__(self, shapename, **kwds):
        self.shapename = shapename
        super().__init__(**kwds)        

class ColoredShape(Shape):
    def __init__(self, color, **kwds):
        self.color = color
        super().__init__(**kwds)

cs = ColoredShape(color='red', shapename='circle')

这里为什么要在Shape中调用super()?我的理解是,这会调用 object.__init__(**kwds),因为 Shape 隐式继承自 object

即使没有那个声明,我们也已经

据我所知,删除这一行会产生相同的行为和功能:

class Shape:  # (object)
    def __init__(self, shapename, **kwds):
        self.shapename = shapename
        # super().__init__(**kwds)

class ColoredShape(Shape):
    def __init__(self, color, **kwds):
        self.color = color
        super().__init__(**kwds)
    def check(self):
        print(self.color)
        print(self.shapename)

cs = ColoredShape(color='red', shapename='circle')

cs.check()
# red
# circle

这里 Shape 中的 super() 的目的是什么?

重点是协同多重继承。整篇文章的重点是协同多重继承,真的。

你看Shape,除了object,你没有看到任何parents。当然可以,但这并不意味着 Shape 之后 MRO 上没有任何兄弟姐妹或其他任何东西。 super() 不仅仅适用于 super类;它在 method resolution order 中搜索该方法的下一个实现。比如文章后面的一个类是

class MovableColoredShape(ColoredShape, MoveableAdapter):
    pass

在这种情况下,Shape.__init__ 需要调用 super().__init__,或 MoveableAdapter.__init__ 并且将跳过所有进一步的 __init__ 调用。

我看到@user2357112 已经提供了正确答案。我正在研究一个示例,虽然我会离开这里,因为它几乎就是 user2357112 所描述的内容。考虑这样的 mixin class:

class PositionMixin:
    def __init__(self, x=0, y=0, **kwds):
        super().__init__(**kwds)
        self.x = x
        self.y = y

假设您将其应用到您的 ColoredShape class:

class ColoredShape(Shape, PositionMixin):
    def __init__(self, color, **kwds):
        self.color = color
        super().__init__(**kwds)

如果Shape没有调用super.__init__,那么当你这样做的时候:

myshape = ColoredShape('red', shapename='circle', x=1, y=1)
print(myshape.x, myshape.y)

你得到:

Traceback (most recent call last):
  File "supertest.py", line 18, in <module>
    print (myshape.x, myshape.y)
AttributeError: 'ColoredShape' object has no attribute 'x'

形状中对 super.__init__ 的调用是调用 PositionMixin 上的 __init__ 方法所必需的。