携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情
0 环境
- 编辑器:idea或vscode
- 系统版本:windows10
- python版本:3.9.6
1 使用
比如我想知道,如下代码,fn函数执行时间,就被下面的print打印出来执行的时间了。注意和之前不同之处,需要导入datetime,记录开始和结束时间。
import datetime
def logger1(fn):
def wrap(*args, **kwargs):
start = datetime.datetime.now()
ret = fn(*args, **kwargs)
end = datetime.datetime.now()
print("{} called took {}".format(fn.__name__, end - start))
return ret
return wrap
def sleep(val):
time.sleep(val)
if __name__ == '__main__':
logged_sleep = logger1(sleep)
logged_sleep(4)
有么有方式替代logged_sleep = logger1(sleep),假如我有多个函数需要被logger1调用,每次都要这么定义,不够优雅,@logger1的方式就可以替代,放的位置如下图。
2 总结
什么是装饰器,需要满足参数是一个函数,而后它的返回值也是一个函数的条件的,就可以作为装饰器,现在呢,为了优雅,我们不用logged_sleep = logger1(sleep)这种,返回值赋值给logged_sleep变量的方式调用了,而是用@这种语法来写,它放在装饰器的入参函数上面,比如作为logger1函数的入参函数,好,有了这个资格,@logger1就是装饰器了,把它在sleep函数上,以后就不用logged_sleep = logger1(sleep)的方式调用了,这里是有区别的,logged_sleep = logger1(sleep)的方式是函数赋值,而@的这种方式呢,可以类比为,我有一朵花,但我不一定要送人。那么反过来,我有一个装饰器的函数,但是我不一样在每个函数的头上添加这个@xxx,而是在我需要的时候安装它,说白了就是,logged_sleep = logger1(sleep)和@xx这两种情况,建议分情况使用,而不是无脑的@xxx到底,当然你就要这么干也是可以的,毕竟是你写的,你说了算。还有使用场景常用于权限认证等方面。