2012-01-19 22 views
5

如何在類定義後使類方法變爲靜態?換句話說,爲什麼第三種情況會失敗?從類之外的現有方法創建靜態方法? (「未綁定方法」錯誤)

 

>>> class b: 
... @staticmethod 
... def foo(): 
... pass 
... 
>>> b.foo() 
>>> class c: 
... def foo(): 
... pass 
... foo = staticmethod(foo) 
... 
>>> c.foo() 
>>> class d: 
... def foo(): 
... pass 
... 
>>> d.foo = staticmethod(d.foo) 
>>> d.foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead) 

回答

6

的類被定義後,foo是未綁定方法的對象(即捆綁功能的類的包裝),而不是一個函數。包裝將嘗試將類的實例(self)作爲第一個參數傳遞給該函數,因此它會抱怨說您沒有給出它。

staticmethod()應該只用於功能。雖然類仍在定義中(如bcfoo()仍然是一個函數,因爲方法包裝器在類定義完成時應用。

可以從未綁定的方法對象中提取函數,應用staticmethod()並將其分配給類。

class d(object): 
    def foo(): 
     pass 

d.foo = staticmethod(d.foo.im_func) 

在Python 3中,沒有未綁定的實例方法(存儲在類上的方法是普通函數)。所以,你的原代碼實際上在Python 3的

做工精細,關於雙方的Python 2和Python 3工作的方式是:

d.foo = staticmethod(d.__dict__['foo']) 

(這也避免了創建和丟棄的方法包裝。)

+0

不應該是'd.foo.im_func'嗎? – 2012-01-19 01:44:40

+0

是的,謝謝。固定! – kindall 2012-01-19 01:48:26

+0

那麼,你需要用'staticmethod'來標記它們,以便在實例上對它們進行等價調用,而不僅僅是類本身。 'd.foo()'可以使用或不使用'staticmethod'包裝,但'd().foo()'會爆炸(它會嘗試傳遞'foo'不接受的'self')。當然,沒有實例相關的功能需要在實例上調用它們,但對於DRY,引用靜態方法的方法可以並應該將其稱爲self.foo()而不是顯式命名該類。 – ShadowRanger 2016-12-02 17:46:40

5

您必須傳遞該函數,而不是未綁定的方法。

>>> class d: 
... def foo(): 
...  pass 
... 
>>> d.foo = staticmethod(d.foo.im_func) 
>>> d.foo() 
相關問題