Множественное наследование и передача аргументов в унаследованный класс в python

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

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(), создавая линейное наследование в базовых классах среднего уровня? Есть ли альтернатива моей интерпретации? Если нет, то как можно настроить мой, чтобы он работал?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
981
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я изменил определение класса 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

Это связано с правилом в алгоритме ТОиР, которое гласит (Подробнее об этом отвечать здесь, но суть

a class always appears before its ancestor ("monotonicity")

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

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

Здорово! Итак, ошибка на самом деле всегда указывает на фактический порядок?

skrowten_hermit 08.05.2019 08:44

Да, ошибка говорит, это все, Невозможно создать разрешение метода consistent, и проблема согласованности возникла из-за того, что я указал в своем ответе @skrowten_hermit.

Devesh Kumar Singh 08.05.2019 08:46

Другие вопросы по теме