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






Я изменил определение класса 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)
Да, ошибка говорит, это все, Невозможно создать разрешение метода consistent, и проблема согласованности возникла из-за того, что я указал в своем ответе @skrowten_hermit.
Здорово! Итак, ошибка на самом деле всегда указывает на фактический порядок?