Сначала определите A
, B
и C
, чтобы правильно использовать super
:
class A:
def __init__(self, a, **kwargs):
super().__init__(**kwargs)
assert a == 'a'
self.a = a
class B:
def __init__(self, b, some_num, *args, **kwargs):
super().__init__(**kwargs)
self.b = b
self.some_num = some_num
assert self.some_num <= 30
class C:
def __init__(self, some_num, **kwargs):
super().__init__(**kwargs)
self.some_num = some_num
assert self.some_num >= 10
В частности, обратите внимание, что оба B
и C
заявляют "право собственности" "из some_num
, не беспокоясь о том, что другой класс может его использовать.
Затем определите смешанный класс, который ничего не делает, но гарантирует, что some_num
используется для установки атрибута some_num
.
class SomeNumAdaptor:
def __init__(self, some_num, **kwargs):
self.some_num = some_num
super().__init__(**kwargs)
В-третьих, определите оболочки для B
и C
, которые получают значение some_num
из self
, чтобы добавить его обратно в качестве аргумента ключевого слова (который SomeNumAdaptor
лишен ):
class CWrapper(C):
def __init__(self, **kwargs):
super().__init__(some_num=self.some_num, **kwargs)
class BWrapper(B):
def __init__(self, **kwargs):
super().__init__(some_num=self.some_num, **kwargs)
Это означает, что и B
, и C
"сбросят" значение self.num
.
(Обертка не нужна, если вы также можете измените B
и C
, чтобы сделать some_num
необязательным, и проверьте наличие self.some_num
.)
Наконец, определите свои комбинированные классы в терминах SomeNumAdaptor
и классов-оболочек. Вы должны унаследовать от SomeNumAdaptor
первый , чтобы BWrapper
и CWrapper
находили some_num
как атрибут, независимо от их относительного порядка.
class CombinedAbc(SomeNumAdaptor, A, BWrapper, CWrapper):
pass
class CombinedCba(SomeNumAdaptor, CWrapper, BWrapper, A):
pass
combo_cba = CombinedCba(a='a', b='b', some_num=25)
combo_abc = CombinedAbc(a='a', b='b', some_num=15)
Все вышеизложенное предполагает, что ни B
, ни C
не хранят измененное значение своего some_num
аргумента атрибута. Если это так, вам понадобятся более сложные обертки для его обработки, вероятно, они будут делать больше, чем просто передавать полученное значение в __init__
. Обратите внимание, что это может указывать на более фундаментальную проблему с наследованием от B
и C
одновременно.