2013-09-27 23 views
8

我有以下代碼。爲什麼在這個例子中,子類不會繼承python中父類的方法?

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方法。

編輯:它工作正常,如果你打電話超級被註釋掉。

+3

不確定,但不是因爲__variablename是一個特殊變量嗎? http://stackoverflow.com/a/1301369/2537322 – meyer9

+0

更奇怪的是,爲什麼它*工作*如果你調用'super()'? – 2013-09-27 04:08:05

+0

不是一個答案,但增加了更多細節 - 如果你將它從__baz改到baz,這兩個調用都打印21.如果你調用'super()'並且以'__baz'離開,他們會打印'40'和'21'分別。 – 2013-09-27 04:09:32

回答

7

基於當前/包含命名空間,雙下劃線屬性的名稱已損壞。在函數foo中,當前名稱空間爲Foo,所以當python查找self.__baz時,由於名稱修改方案,它實際上會查找。由於在Foo中沒有任何地方確實設置了__baz屬性,因此該類沒有_Foo__baz屬性(因爲您在Bar的方法中設置了self.__baz,所以它具有_Bar__baz屬性)。

當然,你可能已經注意到,如果你打電話Foo.__init__(self)Baz.__init__(直接或通過super),你會看到問題消失,因爲Foo.__init____baz(即_Foo__baz)。

+0

所以foo方法不是繼承正確的?我對這裏發生的事情有點困惑...... –

+0

@ user1988876 - 'foo'方法*被*繼承。但是,當你調用它時,它試圖訪問的屬性*缺少*。當python在'Bar'類的定義內看到'self .__ baz'時,它會將它改爲'self._Bar__baz'。當它在'Foo'類的定義中看到'self .__ baz'時,它將它改變爲'self._Foo__baz'。這裏的整個想法是這樣的:'Foo'內的'self .__ baz'可以區別於'Bar'裏面的'self .__ baz'。 – mgilson

+0

所以實際上他叫「super」(Bar,self)。__init __()'子類Bar的對象有兩個**屬性,一個是'_Bar__baz'(因爲他在子類init方法中使用'self .__ baz = 21'),另一個是父類**的'_Foo__baz'。 *錯誤的情況下(如果他沒有調用super(Bar,self).__ init __()')Bar的對象只有一個屬性是_Bar__baz ** ** –

3

當你用python命名帶有雙下劃線的變量時,成員名稱將被混淆。聲明__baz爲您提供會員_Bar__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並不是不好的做法嗎? * –

相關問題