2015-02-18 58 views
0

我想在Python中編寫一個裝飾器來限制函數在一段時間內被調用的次數。我預計使用這樣的:我如何評價Python 2.7中的函數與裝飾器?

@ratelimit(seconds=15) 
def foo(): 
    print 'hello' 

start = time.time() 
while time.time() - start < 10: 
    foo() 

> 'hello' 
> 'hello' 

所以裝飾功能,可以稱得上是最大的每一次seconds的。在實施這方面我有這個,但我不知道正確的方式來持久last_call後續調用之間它不工作:下面

import time 

def ratelimit(seconds=10): 

    last_call = None # Never call decorated function 
    def decorator(func): 


     def wrapper(*args, **kwargs): 

      if last_call is None or time.time() - last_call > seconds: 
       result = func(*args, **kwargs) 
       last_call = time.time() 
       return result 

      return wraps(func)(wrapper) 

    return decorator 
+0

這是Python 3嗎?然後使用'nonlocal'來更新一個像'last_call'這樣的自由變量。 – 2015-02-18 00:46:33

+0

Python 2.7沒有非本地的。 – nickponline 2015-02-18 00:53:48

+0

是的,但作爲dup中的[其中一個答案](http://stackoverflow.com/a/2009474/846892)建議您可以在Python 2中使用可變項目(如列表或詞典)來存儲和更新這些項目。函數屬性也應該起作用。 – 2015-02-18 00:57:54

回答

2

的代碼在Python 2.7的工作對我罰款。

import time 
from functools import wraps 

last_called = dict() # When last called, and with what result 

def ratelimit(seconds=10, timer=time.time): 
    def decorator(func): 
     last_called[func] = None 

     @wraps(func) 
     def wrapper(*args, **kwargs): 
      now = timer() 
      call_data = last_called.get(func, None) 
      if call_data is None or now - call_data[0] >= seconds: 
       result = func(*args, **kwargs) 
       last_called[func] = (now, result) 
      else: 
       result = call_data[1] # Replay rate-limited result 
      return result 
     return wrapper 
    return decorator