2016-08-28 7 views
0

ここでは、BCの両方が異なる__init__()パラメータから派生しています。私の質問は、次の例でself.a、self.b、self.c1、self.c2を初期化するためにここに正しい/エレガントなコードを書く方法です。 もう1つの質問かもしれません - __init()__関数でこの変数設定を行うのは良いコーディング方法ですか、より簡単な__init__()関数を使用する方が良いですし、後で各クラスに対してset()関数を実行します__init()__に?親クラスを持つpython多重継承は異なる__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__を呼び出すとそれらを渡すことで、それらを連携させることができます。あなたの例のクラス階層については

、あなたはこのような何か行うことができます:あなたは(というself.aなどを使用するよりも)直接引数の値を使用するようにDを望んでいた場合、あなたは両方取ることができることを

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 

は注意を名前付き引数とまだsuper()コールにそれらを渡し、それら:親クラスのいくつかは、彼らのorigiで(引数を保存しない場合

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! 

いくつかの引数に受け入れ、合格することが重要ですこれらの値が必要です。このコードスタイルを使用して、一部の引数(たとえば、super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs))の変更された値を渡すこともできます。

さまざまな引数を使用したこの種のコラボレーション多重継承は、位置引数を使用して作業を行うことはほとんど不可能です。ただし、キーワード引数を使用すると、呼び出しの名前と値の順序は関係ありません。したがって、名前付き引数と**kwargsを同時に渡すのは簡単です。 *argsを使用するとうまくいきません(最近のPython 3のバージョンでは、で関数を呼び出す方法の柔軟性が増します(例えば、1回の呼び出しで複数のアンパックを許可するなど)。f(*foo, bar, *baz))。

あなたが明示的に引数をsuperに渡しているので、Python 3を使用していた場合は、コラボレーション関数の引数を「キーワードのみ」にすることができます。混在し、あなたのメソッドを位置引数で呼び出そうとしています。 *を他の名前付き引数の前の引数リストに入れてください:def __init__(self, *, c1, c2, **kwargs):

+0

ありがとう@Blckknght、これは非常に素晴らしい説明です! –