Поддержание читабельности при использовании super () для прямого множественного наследования - PullRequest
0 голосов
/ 07 февраля 2019

Для случая базового множественного наследования:

class A:
    def __init__(self, a):
        self.a = a

class B:
    def __init__(self, b):
        self.b = b

class C(A, B):
    def __init__(self, a, b): 
        A.__init__(self, a)
        B.__init__(self, b)

Я не понимаю, почему следует использовать super().Я полагаю, вы могли бы реализовать это с помощью kwargs, но это, безусловно, менее читабельно, чем описанный выше метод.Мне еще предстоит найти какие-либо ответы на переполнение стека, которые в пользу этого метода, но наверняка для этого случая он является наиболее удовлетворительным?

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

Этот ответ имеет дело с использованием super в этом сценарии, но без передачи аргументов __init__, как здесь, и этот ответ имеет дело с передачейаргументы, но опять же наследство алмазов.

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Один правильный способ использования super здесь будет

class A:
    def __init__(self, a, **kwargs):
        super().__init__(**kwargs)
        self.a = a


class B:
    def __init__(self, b, **kwargs):
        super().__init__(**kwargs)
        self.b = b


class C1(A, B):
    pass


class C2(A, B):
    def __init__(self, a, b, **kwargs):
        super().__init__(a=a, b=b, **kwargs)


c1 = C1(a="foo", b="bar")
c2 = C2(a="foo", b="bar")

Порядок разрешения метода для C равен [C, A, B, object].Каждый раз, когда вызывается super(), он возвращает прокси для класса next в MRO, в зависимости от того, где super() вызывается в то время.

При определенииC, в зависимости от того, хотите ли вы определить C.__init__ с помощью подписи, в которой упоминаются два аргумента A и B, необходимые для инициализации.С C1, C1.__init__ не определено, поэтому вместо него будет вызываться A.__init__C2 вам необходимо явно вызвать следующий метод __init__ в цепочке.

C, зная, что это подкласс A и B, должен как минимум предоставитьожидаемые аргументы для известных восходящих __init__ методов.

A.__init__ будут передавать все кроме a методу __init__ следующего класса.

B.__init__ передаст все, что получит , за исключением b.

object.__init__, наконец, будет вызван, и, если все предыдущие классы правильно удалили введенные аргументы ключевого слова, не получатдополнительные аргументы.

Изменение порядка, в котором называются различные __init__, означает изменение MRO, что означает изменение порядка базовых классов.Если вы хотите большего контроля, чем это, то кооперативное множественное наследование не для вас.

0 голосов
/ 07 февраля 2019
class A(object):
    def __init__(self,  *args, **kwargs):
        super(A, self).__init__(*args, **kwargs)
        self.a = kwargs['a']

class B(object):
    def __init__(self,  *args, **kwargs):
        super(B, self).__init__()
        self.b = kwargs['b']

class C(A, B):
    def __init__(self,  *args, **kwargs): 
        super(C, self).__init__(*args, **kwargs)


z = C(a=1,b=2)
z.b

2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...