2016-08-28 2 views
0

Здесь и B, и C получены из A, но с различными параметрами __init__(). Мой вопрос заключается в том, как написать правильный/элегантный код здесь, чтобы инициализировать self.a, self.b, self.c1, self.c2 в следующем примере? Возможно, еще один вопрос: это хорошая практика кодирования, чтобы сделать эту переменную в функции __init()__ или лучше использовать более простую функцию __init__() и сделать функцию set() для каждого класса позже, что кажется не таким простым, как просто сделать это в __init()__?Наследование python multi с родительскими классами имеет разные __init __()

class A(object): 
    __init__(self,a): 
     self.a=a 
class B(A): 
    __init__(self,a,b): 
     super(B,self).__init__(a) 
     self.b=b 
class C(A): 
    __init__(self,a,c1,c2): 
     super(C,self).__init__(a) 
     self.c1=c1 
     self.c2=c2 

class D(B,C) 
    __init__(self,a,b,c1,c2,d): 
     #how to write the correct/elegant code here to initialize self.a,self.b,self.c1,self.c2? 
     #can I use super(D,self) something? 
     self.d=d 
     self.dd=self.a+self.b+2*self.c1+5*self.c2+3*self.d 

d=D(1,2,3,4,5) 
+0

Благодарим вас за комментарий @Karin, но вопрос здесь другой и более открытый. –

ответ

1

Множественное наследование в 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):.

+0

Спасибо @Blckknght, это очень приятное объяснение! –

Смежные вопросы