2013-03-18 53 views
1

解決方案:錯誤是我的函數實際上是一個方法。模擬一個函數的靜態變量

我想使用裝飾器來模擬一個函數的變量。爲什麼我在下面最後一行出現這個錯誤? global name 'onecmd' is not defined

def static_var(varname, initial_value): 
    def decorate(func): 
     setattr(func, varname, initial_value) 
     return func 
    return decorate 

@static_var("last", None) 
def onecmd(self, line): 
    if line == "lastcmd": 
     line = onecmd.last 
    else: 
     onecmd.last = line 

回答

4

你的代碼似乎希望能夠訪問onecmd作爲一個全球性的,但是這是一個方法。在模塊級別定義的函數確實可以通過它們的名稱到達(因爲它們以全局方式存儲),但類方法只存儲在類對象中。

你需要找到函數對象或者通過在其上定義了這個,或者通過self屬性,緊接着回類,然後該函數的類:

@static_var("last", None) 
def onecmd(self, line): 
    onecmd = type(self).onecmd.im_func # im_func is the wrapped function 
    if line == "lastcmd": 
     line = onecmd.last 
    else: 
     onecmd.last = line 

既然你已經有一個類方法,你會好起來的存儲變量上代替:

class Foo(object): 
    last = None 

    def onecmd(self, line): 
     if line == "lastcmd": 
      line = type(self).last 
     else: 
      type(onecmd).last = line 

,甚至使之成爲一個類的方法來代替:

class Foo(object): 
    last = None 

    @classmethod 
    def onecmd(cls, line): 
     if line == "lastcmd": 
      line = cls.last 
     else: 
      cls.last = line