Множественное наследование в Python требует, чтобы все классы взаимодействовали, чтобы заставить его работать. В этом случае вы можете заставить их сотрудничать, если метод __init__
в каждом классе принимает произвольные **kwargs
и передает их при вызове super().__init__
.
Для примера иерархии классов, вы могли бы сделать что-то вроде этого:
class A(object):
__init__(self,a): # Don't accept **kwargs here! Any extra arguments are an error!
self.a=a
class B(A):
__init__(self, b, **kwargs): # only name the arg we care about (the rest go in **kwargs)
super(B, self).__init__(**kwargs) # pass on the other keyword args
self.b=b
class C(A):
__init__(self, c1, c2, **kwargs):
super(C,self).__init__(**kwargs)
self.c1=c1
self.c2=c2
class D(B,C)
__init__(self, d, **kwargs):
super(D,self).__init__(**kwargs)
self.d=d
self.dd=self.a+self.b+2*self.c1+5*self.c2+3*self.d
Обратите внимание, что если вы хотите D
использовать значение аргументов напрямую (а не с помощью self.a
и т.д.), вы оба могли принять их как именованные аргументы и по-прежнему передавать их в super()
вызова:
class D(B,C)
__init__(self,a, b, c1, c2, d, **kwargs): # **kwargs in case there's further inheritance
super(D,self).__init__(a=a, b=b, c1=c1, c2=c2, **kwargs)
self.d = d
self.dd = a + b + 2 * c1 + 5 * c2 + 3 * d # no `self` needed in this expression!
Прием и передача некоторых аргументах важно, если некоторые из родительских классов не сохраняют аргументы (в их ориги nal form) в качестве атрибутов, но вам нужны эти значения. Вы также можете использовать этот стиль кода для передачи измененных значений для некоторых аргументов (например, с помощью super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)
).
Такое совместное множественное наследование с переменными аргументами практически невозможно сделать работу с использованием позиционных аргументов. Однако при использовании аргументов ключевого слова порядок имен и значений в вызове не имеет значения, поэтому легко передавать именованные аргументы и **kwargs
одновременно без каких-либо нарушений. Использование *args
не работает (хотя последние версии Python 3 более гибки в отношении того, как вы можете вызывать функции с помощью *args
, например, разрешая несколько распаковки за один раз: f(*foo, bar, *baz)
).
Если вы используете Python 3 (я предполагаю, что нет, поскольку вы явно передаете аргументы super
), вы можете сделать аргументы для ваших совместных функций «только для ключевых слов», что помешает пользователям получать очень перепутали и попытались вызвать ваши методы с помощью позиционных аргументов. Просто поставьте оголенный *
в список аргументов перед другими именованными аргументами: def __init__(self, *, c1, c2, **kwargs):
.
Благодарим вас за комментарий @Karin, но вопрос здесь другой и более открытый. –