长期寻找好的装饰器
1. Log
(1) 传统函数
from functools import wrapsimport time
def logit(filename='out.log'): def logging_decorator(func): @wraps(func) def wrapped_func(*args, **kwargs): t = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) log_string = func.__name__ + " was called on " + t print(log_string) with open(filename, 'a') as f: f.write(log_string + '\n') return func(*args, **kwargs) return wrapped_func return logging_decorator
@logit()def my_func1(): pass
@logit('shit.log')def my_func2(): pass
my_func1()my_func2()
(2) 使用类
class Cls_logit(object): _filename = 'cls_logit.log' def __init__(self, func): self.func = func
def __call__(self, *args): t = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) log_string = self.func.__name__ + " called on " + t print(log_string) with open(self._filename, 'a') as f: f.write(log_string + '\n') self.notify() return self.func(*args)
def notify(self): pass
Cls_logit._filename = 'cls_logit2.log'
@Cls_logitdef my_func3(arg1): print('in my_func3 with', arg1)
my_func3(3)
2. Auth验证
from functools import wraps
def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): authenticate() return f(*args, **kwargs) return decorated
@requires_authdef user_some_action(): pass
3. 递归内存优化
from functools import wraps
def memoize(function): print('wizardry here') memo = {} @wraps(function) def wrapper(*args): if args in memo: return memo[args] else: rv = function(*args) memo[args] = rv return rv return wrapper
@memoizedef fibonacci(n): if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2)
# fibonacci(25)
执行上面代码,虽然注释掉了fibonacci(25)
(也就是没调用函数),但还是会打印wizardry here
这行代码,可见装饰器的魔法就在于直接在函数定义后立马替换原来函数。
未完待续