本质上,装饰器(decorator)就是一个返回函数的高阶函数。拿到一个函数,返回一个函数,或者拿到一个类,返回另一个类。
这是普通函数,组装后实现的效果:
def use_logging(func):
print("%s is running" % func.__name__)
return func
def bar():
print('i am bar')
use_logging(bar)()
如果使用装饰器,可以这么做:
def use_logging(func):
print("%s is running" % func.__name__)
return func
@use_logging
def bar():
print('i am bar')
bar()
以上输出,都为如下:
bar is running
i am bar
对比以上两种写法,可以看出,装饰器就是一个返回函数的高阶函数。python提供了@ 符号作为装饰器的语法糖,使我们更方便的应用装饰函数。但使用语法糖要求装饰函数必须return一个函数对象。
Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。下面举一个例子:设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间。
import time
def log(func):
def wrapper(*args,**kw):
t1 = time.time()
func(*args,**kw)
print('%s excute in %s ms'%(func.__name__,1000*(time.time()-t1)))
return wrapper
@log
def slow(x,y,z):
time.sleep(5)
@log
def fast(x,y):
time.sleep(2)
slow(4,5,6)
fast(3,5)
print(slow.__name__)
以上写法有些缺陷,因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。
不需要编写 wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps 就是干这个事的,所以,一个完整的decorator的写法如下:
import time,functools
def log(func):
@functools.wraps(func)
def wrapper(*args,**kw):
t1 = time.time()
func(*args,**kw)
print('%s excute in %s ms'%(func.__name__,1000*(time.time()-t1)))
return wrapper
@log
def slow(x,y,z):
time.sleep(5)
@log
def fast(x,y):
time.sleep(2)
slow(4,5,6)
fast(3,5)
print(slow.__name__)
以上就是装饰器的主要用法,你还知道它的哪些主要应用,欢迎留言。
参考:
https://www.liaoxuefeng.com/wiki/
https://www.cnblogs.com/hiwuchong/p/8136982.html
本文分享自 程序员郭震zhenguo 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!