Множественное наследование и передача аргументов наследуемому классу в Python - PullRequest
1 голос
/ 08 мая 2019

У меня определены следующие классы:

class A(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = ""

    def mA1(self):
        print "Method 1 in A"

    def mA2(self):
        print "Method 2 in A"

    def mA3(self):
        print "Method 3 in A"

class B(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.x = 0

    def mB1(self):
        print "Method 1 in B"

class C(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = ""
        self.y = 1

    def mC1(self):
        print "Method 1 in C"

    def mC2(self):
        print "Method 2 in C"

Как видно, они принимают одинаковые входные аргументы в конструкторе.Теперь я хочу создать класс D, который наследует от всех A, B и C, чтобы я мог напрямую передавать аргументы в конструктор D следующим образом:

clsT = D(1, 2)

Итак, я опробовал, как упоминалось здесь следующие пересмотренные определения:

class A(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = ""

    def mA1(self):
        print "Method 1 in A"

    def mA2(self):
        print "Method 2 in A"

    def mA3(self):
        print "Method 3 in A"


class B(A):
    def __init__(self, **kw):
        super(B, self).__init__(**kw)
        self.x = 0

    def mB1(self):
        print "Method 1 in B"


class C(A):
    def __init__(self, **kw):
        super(C, self).__init__(**kw)
        self.c = ""
        self.y = 1

    def mC1(self):
        print "Method 1 in C"

    def mC2(self):
        print "Method 2 in C"


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


ci = D(1, 2)

print "a = ", ci.a
print "b = ", ci.b
print "c = ", ci.c
print "x = ", ci.x
print "y = ", ci.y

Вышеприведенное, похоже, не работает и выдает мне следующую ошибку:

    class D(A, B, C):
TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution
order (MRO) for bases B, C, A

Что может быть не так?Действительно ли требуется, чтобы B и C включали super(), создавая линейное наследование в базовых классах среднего уровня?Есть ли альтернатива моей интерпретации?Если нет, то как мой можно настроить, чтобы он работал?

1 Ответ

2 голосов
/ 08 мая 2019

Я изменил определение класса D следующим образом, и оно сработало

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

Таким образом, общий класс будет выглядеть так (я удалил методы, чтобы код был коротким)

class A(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = ""

class B(A):
    def __init__(self, **kw):
        super(B, self).__init__(**kw)
        self.x = 0

class C(A):
    def __init__(self, **kw):
        super(C, self).__init__(**kw)
        self.c = ""
        self.y = 1


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


c = D(1, 2)
print(c.a, c.b, c.x, c.c, c.y)

Выход будет

1 2 0  1

Это связано с правилом в алгоритме MRO , который гласит (подробнее в этом ответе здесь, но суть

класс всегда появляется перед своим предком («монотонность»)

Следовательно, B и C должны появляться перед A, так как A является предком B и C

Или другими словами: D наследуется от A, B и C. Поскольку B и C уже наследуются от A, Python теперь не может определить, на какой класс искать методы в первую очередь; либо A, либо B и C, если вы используете старый порядок определения. D(A, B, C)

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