2010-09-12 144 views
4

這跟在幾個小時前我問過的一個問題。對基類行爲感到困惑

我有這樣的代碼:

class A(object): 
    def __init__(self, a): 
     print 'A called.' 
     self.a = a 

class B(A): 
    def __init__(self, b, a): 
     print 'B called.' 

x = B(1, 2) 
print x.a 

這給了錯誤:AttributeError: 'B' object has no attribute 'a',符合市場預期。我可以通過撥打super(B, self).__init__(a)來解決這個問題。

不過,我有這樣的代碼:

class A(object): 
    def __init__(self, a): 
     print 'A called.' 
     self.a = a 

class B(A): 
    def __init__(self, b, a): 
     print 'B called.' 
     print a 

x = B(1, 2) 

,其輸出是:

B called. 
2 

爲什麼這項工作?更重要的是,當我沒有初始化基類時它是如何工作的?另外請注意,它不會調用A的初始值設定項。是不是因爲當我做了:

def __init__(self, b, a)

我聲明b是的B屬性?如果是,我該如何檢查b是哪個類的屬性 - 子類或超類?

回答

4

您定義它的方式B沒有任何屬性。當你做print a時,a引用__init__方法中的局部變量a,而不是任何屬性。

如果用print self.a替換print a,您將收到與以前相同的錯誤消息。

+0

啊,我現在明白了。謝謝! – Jeremy 2010-09-12 14:57:12

+0

我是否正確地調用'b'類的屬性或者是否存在其他一些Pythonic術語? – Jeremy 2010-09-12 15:01:12

+0

嗯,最重要的是,'實例變量'和'實例屬性'有什麼區別? – Jeremy 2010-09-12 15:02:43

2

在你的第二個代碼,調用print a作品,因爲你要打印作爲參數傳遞給B的__init__函數傳遞的變量,而不是self.a變量(這是不是因爲A.__init__初始化不叫)。一旦離開__init__功能的範圍,您將無法訪問a

+0

所以'a'類似於類屬性? – Jeremy 2010-09-12 14:55:04

1

簡短的回答是,__init__不是其他語言的意義上的構造函數,如C++。在創建「裸」對象後,它實際上只是一個在對象上運行的函數。 B的__init__函數通常負責調用A的__init__,但它不必 - 如果A.__init__永遠不會被調用,那麼A的屬性a不會被添加到該對象,因此當您嘗試訪問時會出現錯誤它。

1

要解決這個問題,你需要使用

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

請務必聲明類作爲新的樣式對象,你已經做的事情

[編輯:澄清]

+2

You mean't'super(B,self).__ init __(a)'I guess :) – user225312 2010-09-12 14:57:44