2010-03-20 27 views
12

我有一個私人方法def __pickSide(self):在父類中,我想要在子類中重寫。但是,子類仍然會調用繼承的def __pickSide(self):。我如何覆蓋該功能?子類的函數名與父函數名完全相同。如何覆蓋python中父類的函數?

+3

請不要使用所有'__'。他們很混亂。 Python中確實沒有「私有」。他們使簡單的事情看起來很混亂。請使用顯示您的問題的最小代碼示例更新您的問題。 – 2010-03-20 18:36:52

+0

這是我遇到的代碼...你還想要什麼?我知道在Python中仍然可以訪問「私有」函數和變量,但是不會使用所有公共函數在使用該類時會使事情更加混亂? – wrongusername 2010-03-20 18:47:25

+0

「這是代碼」?什麼代碼?你能否更新這個問題來真正提供實際不起作用的實際代碼樣本?很難猜測你的代碼是什麼樣的。假設事情很容易;很容易認爲錯誤。 「你還想要什麼?」碼。要看看,看看你實際犯了什麼錯誤,而不是我假設你犯了什麼錯誤。 – 2010-03-20 18:53:05

回答

33

讓我們看看最簡單的例子:

from dis import dis 

class A(object): 
    def __pick(self): 
     print "1" 

    def doitinA(self): 
     self.__pick() 

class B(A): 
    def __pick(self): 
     print "2" 

    def doitinB(self): 
     self.__pick() 

b = B() 
b.doitinA() # prints 1 
b.doitinB() # prints 2 

dis(A.doitinA) 
print 
dis(B.doitinB) 

拆卸如下:

8   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (_A__pick) 
       6 CALL_FUNCTION   0 
       9 POP_TOP 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE 

15   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (_B__pick) 
       6 CALL_FUNCTION   0 
       9 POP_TOP 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE 

正如你所看到的,Python的軋液以兩個下劃線開頭的函數名(以及訪問這些名稱!!)轉換爲包含類名稱的名稱 - 在此例中爲_A__pick_B__pick)。這意味着定義函數的類將確定調用哪個方法。

該解決方案很簡單,通過刪除雙下劃線來避免僞私有方法。例如,使用_pick而不是__pick

5

您看到的問題是,即使在調用中,雙下劃線也會破壞函數名稱。這可以防止多態性正常工作,因爲它被修改的名稱是基於方法定義的類的名稱,而不是被引用的對象的類的名稱。用其他東西代替雙下劃線將解決這個問題。

3
  • 使用__foo名稱mangles方法的名稱使它在您需要時更難以訪問它。我建議不要使用它們,這使得測試更順利。

  • Python中沒有私有的,如果有的話,它會阻止你這樣做。 (這是私人的東西,在這有它的語言點。)

  • 共同約定以表明屬性不是類的公共接口它使用一個領先的一部分下劃線,像_foo 。這足以讓您的代碼清楚地將您的內部細節與公共API分隔開來。