2011-10-22 230 views
10

此代碼拋出一個異常,AttributeError,「wtf!」,因爲A.foo()正在調用B.foo1(),是不是應該撥打A.foo1()?我怎樣才能迫使它調用A.foo1()(和內A.foo()任何方法調用應該調用A.*調用覆蓋方法,超類調用覆蓋方法

class A(object): 
    def foo(self): 
     print self.foo1() 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
+1

你基本上要求Python拋棄動態性和虛擬方法,並*以某種方式*根據函數的詞法定義跳過部分屬性查找鏈。不會發生。 – delnan

回答

5

它是否按預期運行,作爲世界編程語言工作的100%。子類重寫父類的所有方法。

但是,如果你真的很想打電話給A.foo1(),你可以這樣做(我不能保證)。在任何情況下,你都不能這樣做,因爲這違反了所有良好編程原則。

class A(object): 

    def foo(self): 
     A.foo1(self) 
2

在代碼:

def foo2(self): 
    super(B, self).foo() 

自我是B.

的實例。當從A衍生的方法是通過B的一個實例,將開始尋找在從命名空間稱爲B,並且只有在找不到該方法時(例如,不被B覆蓋),使用來自A的實現,但始終自我參考B.在任何情況下,self都是A的實例。

6

In A類,而不是調用self方法,您需要調用A方法並手動傳入self

這不是正常的做事方式 - 你應該有一個真的這樣做的好理由。

class A(object): 
    def foo(self): 
     print A.foo1(self) 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
-1

可以看到Python在這裏做了什麼,但重寫的方式有點極端。當A類定義了100個屬性並且B類繼承了這些屬性並添加了另外1個屬性的情況下。我們希望能夠讓B的__init __()調用A的__init __(),並讓B的代碼只定義它的單個屬性。同樣,如果我們在A中定義一個reset()方法來將所有屬性設置爲零,那麼B的相應reset()方法應該能夠調用A的reset()方法,然後將單個B屬性替換爲零不得不復制A的所有代碼。 Python正在變得困難,這應該是面向對象編程的主要優勢;也就是代碼的重用。這裏最好的選擇是避免重寫我們真正想要重用的方法。如果你想在這裏得到與Python併發症的感覺,試試這個代碼:

class X(object): 
    def __init__ (self): 
     print "X" 
     self.x = 'x' 
     self.reset() 
     print "back to X" 
    def reset (self): 
     print "reset X" 
     self.xx = 'xx' 

class Y(X): 
    def __init__ (self): 
     print "Y" 
     super(Y,self).__init__() 
     self.y = 'y' 
     self.reset() 
     print "back to Y" 
    def reset (self): 
     print "reset Y" 
     super(Y,self).reset() 
     print "back to reset Y" 
     self.yy = 'yy' 

aY = Y() 

(爲了使這項工作正常,消除__init __()類Y的self.reset()調用)