Below for you to share a python decorator-limit the number of function calls method (10s call once), with a good reference value, I hope to be helpful. Come and see it together.
This is the most recent big company's face test paper, write an adorner, the limit function is called every 10s. It was written, only the approximate code, came back to review the basic knowledge of the Python decorator, the code is finished. decided to write a blog post.
The adorner is divided into an adorner with parameters and an adorner without parameters.
#不带参数的装饰器 @dec1 @dec2def func (): #这个函数声明等价于func = DEC1 (DEC2 (func)) #带参数的装饰器 @dec (Some_args) def func (): ... # This function declaration is equivalent to Func = Dec (Some_args) (func)
Some details to note for adorners without parameters
1. About the adorner function (decorator) itself
Thus an adorner typically corresponds to two functions, one is the decorator function, which is used to perform some initialization operations, and one is the decorated_func used to implement additional processing of the decorated function func. and in order to maintain a reference to Func, Decorated_func is generally used as the intrinsic function of decorator
def decorator (func): def decorator_func () func () return Decorated_func
The decorator function is called only once when the function is declared.
The adorner is actually a syntactic sugar, which is called after the function is declared, generates DECORATED_FUNC, and replaces the reference to the Func symbol with Decorated_func. After each call to the Func function, the actual call is Decorated_func (this is very important, after decorating, in fact, each call is Decorated_func).
>>> def decorator (func): ... Def decorated_func (): ... Func (1) ... Return decorated_func ... #声明时就被调用 >>> @decorator ... def func (x): ... Print x ... decorator being called #使用func () function is actually using the Decorated_func function >>> func () 1>>> func.__name__ ' Decorated_func '
If you want to ensure that the function name of the returned Decorated_func is the same as the function name of Func, you should add Decorated_func.name = Func.name before the Decorator function returns DECORATED_FUNC. In addition, the Functools module provides a wraps decorator to complete this action.
# @wraps (func) operation equals # before return decorated_func, execution #decorated_func.__name__ = Func.__name__#func passed in as an adorner parameter, #decorated_ Func is passed as a parameter of the function returned by wraps >>> def decorator (func): ... @wraps (func) ... Def decorated_func (): ... Func (1) ... Return decorated_func ... #声明时就被调用 >>> @decorator ... def func (x): ... Print x ... decorator being called #使用func () function is actually using the Decorated_func function >>> func () 1>>> func.__name__ ' Func
The magical functions of local variables of decorator function
Because of the characteristics of the closure (see (1) Part of the closure section of the details), decorator declared variables will be decorated_func.func_closure referenced, so call the decorator method after the end of the The local variables of the decorator method are not recycled, so you can use the local variables of the decorator method as counters, caches, and so on.
It is important to note that if you want to change the value of a variable, the variable must be a mutable object, so it is counted as a counter and should be implemented with a list. and declare a function call once decorator function, so the counters of different functions do not conflict, for example:
#!/usr/bin/env python#filename decorator.pydef Decorator (func): #注意这里使用可变对象 a = [0] def decorated_func (* Args,**keyargs): func (*args, **keyargs) #因为闭包是浅拷贝, if it is an immutable object, the symbol will be emptied after each call, resulting in an error a[0] + = 1 print "%s Bing called%d Times "% (func.__name__, a[0]) return decorated_func@decoratordef func (x): Print X@decoratordef Theotherfunc (x): print X
Here we begin to write code:
#coding =utf-8#!/usr/bin/env python#filename decorator.pyimport timefrom functools import wrapsdef Decorator (func): "Cache for function result, which are immutable with fixed arguments" print "initial cache for%s"% func.__name__ cache = {} @wraps (func) def decorated_func (*args,**kwargs): # function name as key key = func.__name__ result = None #判断是否存在缓存 if key in Cache.keys (): (result, updatetime) = Cache[key] #过期时间固定为10秒 C12/>if time.time ()-updatetime <: print "Limit call 10s", key result = UpdateTime else: print "Cache Expired!!! Can call " result = None else: print" No cache for ", key #如果过期, or no cache calling method if result is NONE:
result = Func (*args, **kwargs) Cache[key] = (result, Time.time ()) return result return decorated_ Func@decoratordef func (x): print ' call func '
Test it casually, basically no problem.
>>> from decorator import funcinitial cache for func>>> func (1) No cache for Funccall func>>> fu NC (1) Limit call 10s func1488082913.239092>>> func (1) Cache expired!!! Can Callcall func>>> func (1) Limit call 10s func1488082923.298204>>> func (1) Cache expired!!! Can Callcall func>>> func (1) Limit call 10s func1488082935.165979>>> func (1) Limit call 10s func1488082935.165979