2014-11-24 13 views
0

當我嘗試在裝飾中裝飾具有參數的方法時,它給我一個self未定義。如果改爲將類別val更改爲類變量並使用MyCls.val它現在給我MyCls未定義!我如何裝飾我的mehtod?使用args獲取裝飾器以使用方法:self不存在

def dodecorate(VAL): 
    def decorate(func): 
     def wrapped(*args,**kwargs): 
      res = func(*args,**kwargs) 
      if res == VAL: 
       res = "one" 
      return res 
     return wrapped 
    return decorate 


class MyCls(object): 
    def __init__(self): 
     self.val = 1 

    @dodecorate(VAL = self.val) 
    def onefrom1(self, x): 
     return x 

EDIT上面是一個抽象我發明來表示原。這是實際的代碼。

def retry_on_invalid_schema(MAX_RETRIES): 
    def retrier(func): 
     def wrapped(*args, **kwargs): 
      tries = 0 
      res = None 
      while tries < MAX_TRIES: 
       try: 
        res = func(*args, **kwargs) 
        assert res.has_key('by') 
        assert res.has_key('id') 
        break 
       except AssertionError: 
        res = None 
        time.sleep(2**tries) 
        tries += 1 
        continue 
      return res 
     return wrapped 
    return retrier 



class Base(object): 

    def __init__(self): 

     self.MAX_RETRIES = 3 

    @retry_on_invalid_schema(MAX_RETRIES = self.MAX_RETRIES) 
    def _get_api_response(self, uri): 
     return json.loads(self._get(uri)) 

    def _get(self, uri): 
     return requests.get(uri).text 
+0

你可以顯示你的'實例'嗎? – Yax 2014-11-24 15:32:55

+0

@Yax我有機會實例化它之前得到錯誤。 – pad 2014-11-24 15:34:34

+2

在類定義期間調用裝飾器函數時,不會存在'self'和'MyCls'。你真的想在這裏做什麼? – jonrsharpe 2014-11-24 15:39:54

回答

1

如果你想在一個實例方法使用現有的裝飾功能,請注意您可以重新定義實例方法在__init__,調用裝飾,而不是直接使用@語法:

class MyCls(object): 

    def __init__(self): 
     self.val = 1 
     self.onefrom1 = dodecorate(self.val)(self.onefrom1) 

    def onefrom1(self, x): 
     return x 

在使用中:

>>> a = MyCls() 
>>> for x in range(3): 
    print a.onefrom1(x) 


0 
one 
2 
+0

我實際上已經將這個問題抽象爲我爲這個問題發明的一個更簡單的問題。實際的裝飾器稍微複雜一點,如果響應不符合預期,則會重新嘗試HTTP請求。它在腳本的其他部分中使用,我想在我的類方法中重用它。 – pad 2014-11-24 15:49:55

+0

抱歉。那麼我會發布實際的東西。認爲它只會分散人們遠離核心問題的外部細節。 – pad 2014-11-24 15:53:03

+0

在問題中更新。 – pad 2014-11-24 15:56:31

0

而不是試圖通過val到裝飾器,你可以通過實例訪問它。 self包含當前實例並傳遞給裝飾器中的包裝方法,因此您可以在裝飾器中作爲第一個參數訪問它。

def decorate(func): 
    def wrapped(instance, *args, **kwargs): 
     res = func(instance, *args, **kwargs) 
     if res == instance.val: 
      res = "one" 
     return res 
    return wrapped 


class MyCls(object): 
    def __init__(self): 
     self.val = 1 

    @decorate 
    def onefrom1(self, x): 
     return x 

c = MyCls() 
print c.onefrom1(1) 
print c.onefrom1(2) 

輸出

one 
2 
+0

謝謝,但我需要一個有參數的裝飾器。 – pad 2014-11-24 15:50:52