унаследованный __init__, кажется, отличается от __init__ родителя - PullRequest
0 голосов
/ 19 апреля 2020

Не могли бы вы объяснить мне следующее поведение? Мое понимание подклассов, вероятно, не полное.

A . Давайте иметь этот простой класс. Он принимает любые аргументы и ничего не делает.

class Base1:
    def __new__(cls, *args):
        return object.__new__(cls)

Его MRO: (<class '__main__.Base1'>, <class 'object'>). Поскольку Base1 не имеет своего собственного __init__, поиск метода __init__ разрешается в родительский (то есть в __init__ объекта). Доказательство:

assert Base1.__init__ is object.__init__  # OK

Давайте вызовем __init__ вручную:

b = Base1(0,1,2)
print(b.__init__)  # prints: <method-wrapper '__init__' of Base1 object at 0x7f46d588ea90>
b.__init__(0,1,2)  # OK <--- init call A

B . Base2 похож на Base1, но имеет свои __init__:

class Base2:
    def __new__(cls, *args):
        return object.__new__(cls)
    def __init__(self, *args):
        print(super().__init__)  # prints: <method-wrapper '__init__' of Base2 object at 0x7f69d053ab50>
        super().__init__(*args)  # FAILURE! <--- init call B

MRO выглядит очень похоже: (<class '__main__.Base2'>, <class 'object'>). Я предполагаю, что super().__init__ является родительским (то есть снова объектом) __init__, но:

b = Base2(1,2,3):

приводит к:

File "test.py", line 18, in __init__
  super().__init__(*args)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)

Обратите внимание на сообщение TypeError. Это __init__ претендует на звание object.__init__.

Так почему же вызовы init A и B различаются?

...