Как наследовать несколько классов (все методы / свойства) с `super` и без вложенного наследования (в отличие от данных решений)? - PullRequest
1 голос
/ 09 июля 2019

Я пытаюсь лучше понять, как использовать множественное наследование с super для упрощения методов и свойств класса. В приведенном ниже примере я пытаюсь наследовать методы класса от A и B до C. Решения, перечисленные ниже, были вдохновлены другими публикациями на эту тему, хотя я считаю, что есть лучший способ.

Быстрый пример

class A():

    def __init__(self):
        self._a1 = 'a1'

    @property
    def a1(self):
        return self._a1

class B():

    def __init__(self):
        self._b1 = 'b1'

    @property
    def b1(self):
        return self._b1

class C(A, B):

    def __init__(self):
        super().__init__()


TEST = C()
print(TEST.a1)
print(TEST.b1)

Поскольку A является первым классом в MRO, super успешно наследует методы из A в C. Но методы B не наследуются успешно.

a1
Traceback (most recent call last):
  File "so.py", line 27, in <module>
    print(TEST.b1)
AttributeError: 'C' object has no attribute 'b1'

Я понимаю, что один из обходных путей состоит в том, чтобы B наследовал методы A; таким образом, C может наследовать все методы от B, как показано ниже.

РЕШЕНИЕ 1

class A():

    def __init__(self):
        self._a1 = 'a1'

    @property
    def a1(self):
        return self._a1

class B(A):

    def __init__(self):
        super().__init__()
        self._b1 = 'b1'

    @property
    def b1(self):
        return self._b1

class C(B):

    def __init__(self):
        super().__init__()

TEST = C()
print(TEST.a1)
print(TEST.b1)

который выводит

a1
b1

В качестве альтернативы можно обойти использование super для второго класса и получить тот же результат, хотя я думаю, что такой подход не рекомендуется.

РЕШЕНИЕ 2

class A():

    def __init__(self):
        self._a1 = 'a1'

    @property
    def a1(self):
        return self._a1

class B():

    def __init__(self):
        self._b1 = 'b1'

    @property
    def b1(self):
        return self._b1

class C(A, B):

    def __init__(self):
        super().__init__()
        B.__init__(self)

TEST = C()
print(TEST.a1)
print(TEST.b1)

EDIT:

Добавление super().__init__() в конструктор __init__ A и B позволит коду в примере (вверху) работать успешно. Однако этот подход не работает, если четвертый класс D наследует методы от A, B и C. «Решения» были вдохновлены ответами на этот вопрос и этим вопросом (среди прочих).

TL, DR

Как наследовать несколько классов (все методы / свойства) с super (в отличие от решения № 2) и без вложенного наследования (в отличие от решения № 1)?

...