2011-01-13 15 views
3

なぜc.print_a()は 'B'を出力しますか?Pythonでの多重継承問題!

class A(object): 
    def __init__(self): 
     self.some_name = 'A' 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self): 
     self.some_name = 'B' 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     A.__init__(self) 
     B.__init__(self) 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 

class A(object): 
    def __init__(self, some_name='A'): 
     self.some_name = some_name 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self, some_name='B'): 
     self.some_name = some_name 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     A.__init__(self, some_name='AAAAA') 
     B.__init__(self, some_name='BBBBB') 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

感謝を! – Suge

+0

明示しようとしましょう:タイプAとBのオブジェクトの名前をCに設定し、後でprint_aとprint_b関数を呼び出すとこれらの名前が返されるようにしますか? – kriss

+0

はい!上記のようにコードを整形できないのはなぜですか? – Suge

答えて

1

ひとつしかselfだ、とあなたはB.__init__でそのsome_nameを上書きしています。たぶんあなたはC++に慣れていて、A.some_nameB.some_nameという2つの別々のフィールドがあるでしょう。この概念はPythonには当てはまりません.Pythonでは属性が代入時に動的に作成されます。

+0

どうすればこの問題を解決できますか? – Suge

+0

@zkz:どうしたの?これは予想されるPythonの動作です。 – kriss

+0

@zkzの場合、属性ごとに一意の名前を選択し、クラスが互いに踏み込むのを防ぐ必要があります。 –

5

ここには1つのオブジェクトしかありません。 some_nameプロパティは、継承されたすべてのクラスのメソッド間で共有されます。 A.__init__に電話をしてAに設定し、次にB.__init__に設定するとBに変更されます。

また、基本メソッドを間違って呼び出していることにも注意してください。 superを使用します。

class A(object): 
    def __init__(self): 
     self.some_name = 'A' 
     super(A, self).__init__() 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self): 
     self.some_name = 'B' 
     super(B, self).__init__() 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     super(C, self).__init__() 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

上記の2番目のケースで何をすればよいですか?スーパークラス__init__のときに同じキーで求心性パラメータが必要な場所は? – Suge

+0

あなたは何を求めているのか分かりませんが、同じ名前の同じオブジェクトに対して異なるプロパティを設定することはできません。それらは同じ場所に格納された同じオブジェクトです: 'c .__ dict__'は単純に普通のPython辞書です。 –

+2

'self .__ some_name'と言うことができます。これは、そのクラスに対して半個人的な属性を作成します。実際にはegという名前の属性が作成されます。 '_A__some_name'と' _B__some_name'です。これは非常にめったに使用されませんが、私はそれをお勧めしません。 –

1

は、あなたがCはタイプAとBのいくつかのオブジェクトの名前を設定し、後でタイプCのオブジェクトの上にいくつかのprint_aとprint_bメソッドを呼び出すと、バックこれらの名前を取得したいと言いますか?

C++継承モデルを使用してこのタイプの動作を取得できますが、Pythonモデルは非常に異なります。 1つのフィールドセットを持つオブジェクトは1つだけです。 C++の振る舞いを望むなら、おそらく最も単純な方法はサブオブジェクトを宣言することです(そして、それは構成上の継承のよくある悪用のように見えます)。あなたは以下のような何かをしようとしているように

はルックス:あなたの編集のため

class Printable(object): 
    def __init__(self, name): 
     self.name = name 

    def myprint(self): 
     print self.name 

class C(object): 
    def __init__(self): 
     self.a = Printable('A') 
     self.b = Printable('B') 

    def print_a(self): 
     self.a.myprint() 

    def print_b(self): 
     self.a.myprint() 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

上記の例は単なる私の問題の要約です。私の場合、あなたの必要性を満たすことができないほど複雑です.C++のような方法が必要です。 – Suge

+1

@zkz:実際の問題を説明する必要があります。なぜなら、あなたが言っていることはほとんど起こりそうにないからです。**すべての** C++のような継承モデルは、合成を使用して管理することができます。サブオブジェクトからメソッド名を見つけることに問題がある場合は、Pythonのイントロスペクションツール(getattr)を使用するのが非常に簡単です。または、いくつかの共通基本クラスに問題がありますか?実際には、継承は決して必須ではなく、概念をコードにマッピングするための機能だけであり、多くの場合、継承を使って間違いなく実行する必要があることがわかりました。 – kriss