最简单的装饰器
本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
典型的例子
廖雪峰的课程里的习题:在函数执行之后,打印出执行的时间
import time
import functools
def metric(fn):
@functools.wraps(fn)
def wrapper(*args, **kw):
start = time.time()
ret = fn(*args, **kw)
end = time.time()
print('%s executed in %s ms' % (fn.__name__, (end - start) * 1000))
return ret
return wrapper
# 测试
@metric
def fast(x, y):
time.sleep(0.0012)
return x + y;
@metric
def slow(x, y, z):
time.sleep(0.1234)
return x * y * z;
f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
print('测试失败!')
elif s != 7986:
print('测试失败!')
带参数的装饰器
如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:
import time
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log("calling: ")
def fast(x, y):
time.sleep(0.0012)
return x + y;
fast(1, 2)
装饰器的用处
有一个概念叫【面向切面编程】,一个最典型的例子就是需要在一系列函数运行时,增加一条日志。如果把加日志的代码直接放到目标函数里,工作量大,而且后期不好维护。使用装饰器开源很方便的