Вызов `super()` в родительском классе

Я читаю Raymond Hettinger Pythons 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')

Зачем нужно звонить super() в Shape здесь? Я понимаю, что это вызывает object.__init__(**kwds), поскольку Shape неявно наследует от object.

Даже без этого утверждения мы уже

  • установлен shapename уже в родительском __init__,
  • установил дочерний класс color в явном переопределении метода,
  • затем вызывается родительский __init__ с super() в ColoredShape.

Насколько я могу судить, отбрасывание этой строки приводит к такому же поведению и функциональности:

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

В чем цель super() внутри Shape здесь?

Ответ 1

Я вижу, что @user2357112 уже предоставил правильный ответ. Я работал над примером, который, хотя я бы ушел, потому что это довольно много, что описывает user2357112. Рассмотрим класс mixin следующим образом:

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

Скажем, вы примените это к классу ColoredShape:

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__ в форме необходим для вызова метода __init__ на PositionMixin.

Ответ 2

Точка - совместное множественное наследование. На самом деле точка всей статьи - это совместное множественное наследование.

Вы смотрите Shape, и вы не видите никаких родителей помимо object. Конечно, но это не значит, что на MRO после Shape нет ни одного брата или чего-либо еще на MRO. super() относится не только к суперклассам; он ищет следующую реализацию метода в порядок разрешения метода. Например, один из более поздних классов в статье -

class MovableColoredShape(ColoredShape, MoveableAdapter):
    pass

В этом случае Shape.__init__ необходимо вызвать super().__init__ или MoveableAdapter.__init__, и все дальнейшие вызовы __init__ будут пропущены.