2010-08-09 34 views
0

我有類似的東西在我的Python代碼功能類典範

class A: 
    __mess = "Yeap!" 
    def doSome(self): 
    self.FN() 
    def FN(self): 
    pass 

def myFN(self): 
    print self.__mess 

b = A() 
b.FN = myFN 
b.doSome() 

但是,這是行不通的。我錯在哪裏?

蟒2.6.5

UPD:我要重新定義方法(FN)僅對於一個示範性(B)。

UPD2:

import new 
class A: 
    __mess = "Yeap!" 
    def doSome(self): 
    self.FN() 
    def FN(self): 
    pass 

def myFN(self): 
    print self.__mess 

b = A() 
b.FN = new.instancemethod(myFN, b, A) 
b.doSome() 

不工作過。

Traceback (most recent call last):
File "", line 1, in
File "", line 4, in doSome
File "", line 2, in myFN AttributeError: A instance has no attribute '__mess'

+2

看起來像一個無限循環,至少乍一看。你想達到什麼目的? – 2010-08-09 20:55:55

+1

@townsean:他可能希望它無限循環,而不是以類型錯誤退出。 @Ximik:如果你得到一個錯誤,你應該總是發佈錯誤信息,而不是隻說「它不工作」。說出你希望發生的事情,然後會發生什麼。不要讓我們猜測問題出在哪裏。 – sth 2010-08-09 21:00:54

+0

@townsean我正在寫一個守護進程,所以有無限循環。但在這個例子中,這真是多餘的東西。所以我改了一下帖子。 @好的,謝謝你的建議。我會。 – Ximik 2010-08-09 21:03:08

回答

4

myLoopFN是一個函數,而不是一個實例方法。做

import new 
b.loopFN = new.instancemethod(myLoopFN, b, A) 

的問題是,Python的治療實例方法非常略有不同常規的功能:他們得到在它們運行作爲默認的第一個參數的實例。如果你在一個類定義中定義了一個方法,它會自動成爲一個實例方法,這樣當你實例化類時,它就會通過實例。但是,當你定義myLoopFN時,你會這樣做以外的這個類的定義,所以它是一個普通函數而不是實例方法。你可以通過顯式聲明它作爲一個實例方法來解決這個問題。

...

這是噁心,因爲它不是你應該做的;運行時更改實例方法會導致問題。您永遠無法確定您的A是原始A還是修改後的版本,您將無法調試它,因爲您無法確定是否更改了loopFN。這會給你自己會引以爲豪的那種錯誤。

right這樣做的方法是將子類A並覆蓋該方法,以便您可以區分不同的類。

class myA(A): 
    def loopFN(self): 
     #put modified function here 

這樣,您可以實例化修改的類並確定其方法。

編輯

您使用的是雙下劃線變量名,__mess。你(幾乎肯定)不想這樣做。出於某種原因,只有我們的仁慈生命獨裁者和一些其他人才知道,Python會自動將這些__名稱改爲_<class-name>__,以作爲一種人造私有變量。這太可怕了,除此之外沒有理由稱之爲__mess而不是(更好的)mess

如果絕對必須叫它__mess,你可以參考它,如下所示:

def myFN(self): 
    print(self._A__mess) 

(比照當您更改的名稱)。這是討厭的,不和諧的。

+0

請看看upd2。似乎它不起作用。 對於此代碼,子類似乎超標。在Ruby中,這是非常規的代碼風格(也許我錯了,不要長時間使用它)。 – Ximik 2010-08-09 21:12:02

+0

啊,我沒有注意到你在使用雙下劃線變量名。簡短的回答是,不要使用它們。 Python將'__mess'轉換爲'_A__mess',作爲一個人造私有變量。除了「亂七八糟」之外,沒有任何理由稱之爲任何東西。 – katrielalex 2010-08-09 21:17:48

1

關於第二誤差(與__mess):

變化

print self.__mess 

print self._mess 

和更改

class A: 
    __mess = "Yeap!" 

class A: 
    _mess = "Yeap!" 

雙下劃線告訴Python使用name-mangling

另一種方法是改變

def myFN(self): 
    print self.__mess 

def myFN(self): 
    print self._A__mess 
+0

哦,對不起,沒有注意到。謝謝。 – Ximik 2010-08-09 21:16:14

+0

@Ximik:不是問題。每當所有人發帖時都很難頻繁刷新:) – unutbu 2010-08-09 22:43:14