python笔记 装饰器中

49 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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)

image.png

有么有方式替代logged_sleep = logger1(sleep),假如我有多个函数需要被logger1调用,每次都要这么定义,不够优雅,@logger1的方式就可以替代,放的位置如下图。

image.png

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到底,当然你就要这么干也是可以的,毕竟是你写的,你说了算。还有使用场景常用于权限认证等方面。