用了python好久, 惭愧的是一些高级的语法糖就没怎么用过。花了点时间好好研究一下python 装饰器。
所谓装饰, 就是想要对一些已经有的模块做一些修饰工作, 但又不让这个功能侵入到原有代码中去,常用的使用场景例如, 插入日志, 性能测试, 事务处理等等, 有了装饰器, 就可以提取大量函数中与本身功能无关的代码,从而重用代码。
1 | import datetime |
对上面代码的注解:
- 函数log中需要一个func的参数, 也就是用来回调的函数。
- 在now函数前有一个@log, 即之前我们定义的函数
当我们调用now函数时, now()返回了wrapper()函数, 所以now其实变成了wrapper的一个变量, 而后面的log执行其实变成了wrapper()
1 | now() |
这样, 装饰器没有影响到原来的函数,也没影响函数调用的模块。
而多个装饰器,1
2
3
4@decorator1
@decorator2
def now():
print(datetime.datetime.today())
其实等价于 now = decorator1(decorator2(now))
(其实就是说装饰器的调用顺序与其声明的顺序相反)
而如果装饰器自己带参数, 其实就是说装饰器这个函数需要返回一个真正的decorator
比如:(本例子引用自廖雪峰python3装饰器)1
2
3
4
5
6
7def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
若调用1
2
3@log
def now():
print(datetime.datetime.today())
实际上就是
now = decorator(text)(now)
而如果被装饰的那个函数带参数, 则装饰器的函数也需要加入对应参数1
2
3
4
5
6
7
8
9
10def log(func):
def wrapper(text2):
print('%s' % (func.__name__))
return func(text2)
return wrapper
@log
def now(text2):
print(datetime.datetime.today())
print(text2)
比如调用1
now("haha")
输出如下:1
2
3now
2015-06-18 11:20:11.246544
haha
简单的总结到这里, 比较好的例子可以参看
Python修饰器的函数式编程