您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 黄山分类信息网,免费分类信息发布

Python装饰器的妙用,原来它还有这些我们所不知道的作用!

2023/2/16 19:27:17发布36次查看
装饰器模式是一个强大的模式,可以给一个函数增加额外的方法而不用修改原来的代码。比如,当我们需要给原来的代码添加日志记录时,需要将原来的代码进行修改,在函数里面增加日志记录的代码。但如果使用装饰器模式,使用装饰器装饰原来的代码,将日志记录放在装饰器里,就可以避免修改原有代码,同时又实现了所需的功能。这种编程模式就叫做面向切面编程。
python学习交流 643692991
日志记录实例
比如,我们有一个函数 func :
def func():print('func')
现在,我们需要记录一下这个函数执行时的日志记录,即记录一下函数执行的时间,输出执行时间和方法名。日志输出函数如下:
from datetime import datetime as dtdef log(func): print('['+str(dt.now())+']'+func.__name__)func()
好了,当我们想使用 func 函数的时候该怎么做呢?不是直接 func() ,而是如下:
log(func)
那么,会输出:
[2017-09-10 20:51:09.970854]func
这就实现了调用 func 时,同时进行日志记录。但这样做很明显会有问题,就是我们需要把所有调用 func 的地方改为 log(func) ,这很麻烦,并且会需要改很多代码。所以,我们换一种写法:
def log(func):def wrapper():print('['+str(dt.now())+']'+func.__name__)func() return wrapper
请注意,这就是一个装饰器了!
里面那个 wrapper 的意思就是装饰、包裹的意思。我们将 func 函数装饰一下变成了一个新的函数然后返回它。那该如何使用呢?如下:
func = log(func) func()
使用方法就是用log装饰器将func装饰一下后返回覆盖掉原有的func即可。
装饰器语法糖
所谓的语法糖的意思就是添加一个语法,让代码更简单的意思。python为装饰器也提供了一个语法糖,就是 @ 符号。我们可以使用这个符号声明这是一个装饰器。如下,我们使用语法糖的写法给 func 添加 log 这个装饰器:
@logdef func():return print('func')
这样写好后,直接调用 func() 即可同时输出日志了:
[2017-09-10 21:10:50.933021]funcfunc
装饰器给函数传参
我们把 func 函数改一改:
def func(msg):print(--> + msg)
现在,我们要给函数输入参数了,而原来那个 log 装饰器是没有带参数的,所以用不了了。下面,我们就要实现一个可以给函数传参数的装饰器:
def log(func):def wrapper(msg):print('['+str(dt.now())+']'+func.__name__) return func(msg) return wrapper
这样一改, log 就又可以用了,给 func 再加上语法糖:
@logdef func(msg):print(--> + msg)# outputfunc('hello')
output:
[2017-09-10 21:16:26.677027]func-->hello
这样一改,装饰器就又可以用了。那如果我再给 func 又加一个参数呢?再加一个参数呢?我如果给 func 加不定数个参数呢?又该怎么做呢?再改 log 吗?我知道大家心里肯定也意识到了这个方法的不靠谱。
别着急,下面我们就写一个更强力的 log 装饰器,来让装饰器可以装饰任何函数,而不用管那个函数又多少个参数。使用python的可变参数 *args 和关键字参数 **kwargs 即可。修改 log,如下:
def log(func):def wrapper(*args, **kwargs):print('['+str(dt.now())+']'+func.__name__) return func(*args, **kwargs) return wrapper
带参数的装饰器
装饰器本身也可以带参数,比如说,我们给 log装饰器添加一个参数 is_show 用于是否显示日志输出。如下:
def log(is_show=true):def wrapper(func):def inner_wrapper(*args, **kwargs):if is_show:print('['+str(dt.now())+']'+func.__name__) return func(*args, **kwargs) return inner_wrapper return wrapper
作为对比,我们写两个 func:
代码还是有点乱。缩进感觉太麻烦了,所以大家将就着看。我尽量去优化他,像大家推荐一个学习氛围非常好的群,大家都非常乐意解答,乐意交流沟通,就等你的到来。如果你正在学习python,小编欢迎你加入,大家都是python党,不定期分享干货(只有python爬虫,框架,零基础都有),包括我自己整理的一份2017最新的python资料和零基础入门教程,欢迎初学和进阶中的小伙伴。
# 默认显示日志@log(true)def func1():print(func1)# 默认不显示日志@log(false)def func2(): print(func2)
黄山分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录