浅谈Python装饰器的体会

这里不做引入分析,即不一步一步将普通函数转化为装饰器的过程,具体可以百度.

下面直接从最简单的装饰器的构建开始.

首先什么是装饰器,现在先不说,后面具体表述.

 

先提出一个需求  我们要在函数开始执行以及执行完成后分别用日志的形式记录一下.

先定一个获取当前时间字符串的函数.

1
2
def get_time():
    return datetime.now().strftime('%Y-%m-%d %H:%M:%S')

接下来按照需求,构建一个不带参数的装饰器

1
2
3
4
5
6
7
def log(func):
    def wrapper(*args, **kwargs):
        print(f'{get_time()} {func.__name__}开始执行')
        res = func(*args, **kwargs)
        print(f'{get_time()} {func.__name__}结束执行')
        return res
    return wrapper

上面定义好了一个装饰器,作用是是记录开始和结束信息.

下面是被装饰器调'装饰'的函数

 

1
2
3
4
5
6
@log
def fun():
    print('开始计时...')
    time.sleep(3)
    print('结束计时...')
    return 123

 

运行起来的结果:  

 

  

 

 

可以看到,在fun函数开始和结束是,均有额外信息的打印,说明第一个需求完成

 

 

 

但是,如果甲方爸爸增加需求,要求根据不同场景传入参数,打印不同的日志信息,此时必须也要把一些参数传入.

 

以下是成果:

 

 

1
2
3
4
5
6
7
8
9
10
def log_with_params(*param):
    def log(func):
        def wrapper(*args, **kwargs):
            print(f'{get_time()} {func.__name__}开始执行')
            res = func(*args, **kwargs)
            print(f'传入的参数是{param}')
            print(f'{get_time()} {func.__name__}结束执行')
            return res
        return wrapper
    return log

 

  这一次,装饰器多了一层函数,可以具备接收外部参数(而不是被装饰器的函数的参数)功能,还是对同一个函数应用这个装饰器

1
2
3
4
5
6
@log_with_params('params')
def fun():
    print('开始计时...')
    time.sleep(3)
    print('结束计时...')
    return 123 

 

 

 再次执行函数:

 

可以看到外部传入给装饰器的参数已被内部接收到.,基本上大功告成.

但这里还有一个小问题

如果此时打印应用装饰器的函数名称:

 

 

 很明显,这里应该是fun,而不是warpper,应该是把

 

 

 

内层函数名称打印出来了,为了解决这个问题,在wrapper上应用一个系统定义的装饰器.

 

 

 此时打印函数fun的名称,恢复了正常

 

 

 注意这个装饰器使用时需要引入

from functools import wraps

最后以我自己的理解说一下什么是装饰器,对一些函数额外加上一些功能,但又不影响这些函数本身执行过程中定义的一些函数.

当然,类也可以⽤来构建装饰器,这个待笔者学会了再做分析探讨,欢迎大家批评指正
posted @   Mr_huangze  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示