2013-09-27 20 views
8

私は以下のコードを持っています。この例では、子クラスが親クラスからメソッドを継承しないのはなぜですか?

class Foo(object): 
    def __init__(self): 
     self.__baz = 40 
    def foo(self): 
     print self.__baz 

class Bar(Foo): 
    def __init__(self): 
     #super(Bar, self).__init__() 
     self.__baz = 21 
    def bar(self): 
     print self.__baz 

x = Bar() 
x.foo() 
x.bar() 

私はこのエラーを取得する:

Traceback (most recent call last): 
    File "classes.py", line 15, in <module> 
    x.foo() 
    File "classes.py", line 5, in foo 
    print self.__baz 
AttributeError: 'Bar' object has no attribute '_Foo__baz' 

なぜBarに継承されていないfoo方法があります。

EDIT:コメントアウトされているsuperを呼び出すとうまくいきます。

+3

__variablenameが特別な変数であるため、わかりませんが、そうではありませんか? http://stackoverflow.com/a/1301369/2537322 – meyer9

+0

もっと奇妙なことに、なぜあなたは 'super()'を呼び出すのですか? –

+0

答えはありませんが、詳細を追加します - '__baz'から' baz'に変更すると、両方ともprint 21を呼び出します。 'super()'を呼び出して '__baz'として残すと' 40'と '21'それぞれ、 –

答えて

7

重下線属性がその名前が名前空間を含む現在/基づいてを台無しにしています。関数fooでは、現在のネームスペースはFooです。したがって、Pythonがself.__bazを検索すると、実際には名前マングリングスキームのためにが検索されます。 Fooのどこにも実際に__baz属性が設定されているため、クラスには_Foo__baz属性がありません(self.__bazBarに設定しているため、_Bar__bazという属性があります)。もちろん

あなたはおそらく気づいてきたように、あなたが(直接またはsuper経由)Baz.__init__Foo.__init__(self)を呼び出す場合、あなたは問題がFoo.__init__セット__baz(すなわち_Foo__baz)ので、離れて行く表示されます。

+0

fooメソッドは継承されていないので正しいですか?私はここで何が起きているのか少し混乱しています... –

+0

@ user1988876 - 'foo'メソッドは*継承されています。しかし、あなたがそれを呼び出すとき、それがアクセスしようとしている属性は* missing *です。 Pythonが 'Bar'クラスの定義の中で' self .__ baz'を見ると、 'self._Bar__baz'に変更されます。 'Foo'クラスの定義の中で' self .__ baz'を見ると 'self._Foo__baz'に変更されます。ここの考え方は、「Foo」の中の「self .__ baz」と「bar」の中の「self .__ baz」が区別できるようになっています。 – mgilson

+0

実際に彼は 'スーパー(バー、自己)を呼び出すとき。__init __() '子クラスのバーのオブジェクトには、2つの属性があり、1つは' _Bar__baz'です(子クラスのinitメソッドで 'self .__ baz = 21'を行うためです)、その他は親クラス**の' _Foo__baz'ですか? *エラーの場合( 'super(Bar、self).__ init __()'を呼び出さない場合)、バーのオブジェクトには_Bar__bazという属性が1つしかありません**?** –

3

Pythonのような二重のアンダースコアを持つ変数に名前を付けると、そのメンバ名は難読化されます。 __bazを宣言すると、メンバー_Bar__bazが得られます。 __bazに最初の二重のアンダースコアを使用することにより

class Bar(Foo): 
def __init__(self): 
    #super(Bar, self).__init__() 
    self.__baz = 21 
def bar(self): 
    print self._Bar__baz 

x = Bar() 
x.bar() 
>>> 21 
+0

関数 'bar'の定義を変更しました。なぜ私は私の編集で –

+0

+を作ったようにスーパーコールが行われたときに動作するのか知りたいのですが、私にとって有益なトリックを追加しましたが、 '_Bar__baz'を明示的に使用するのは悪い習慣ではありませんか? * –

関連する問題