浅谈Python装饰器的体会
这里不做引入分析,即不一步一步将普通函数转化为装饰器的过程,具体可以百度.
下面直接从最简单的装饰器的构建开始.
首先什么是装饰器,现在先不说,后面具体表述.
先提出一个需求 我们要在函数开始执行以及执行完成后分别用日志的形式记录一下.
先定一个获取当前时间字符串的函数.
def get_time():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
接下来按照需求,构建一个不带参数的装饰器
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
上面定义好了一个装饰器,作用是是记录开始和结束信息.
下面是被装饰器调'装饰'的函数
@log
def fun():
print('开始计时...')
time.sleep(3)
print('结束计时...')
return 123
运行起来的结果:

可以看到,在fun函数开始和结束是,均有额外信息的打印,说明第一个需求完成
但是,如果甲方爸爸增加需求,要求根据不同场景传入参数,打印不同的日志信息,此时必须也要把一些参数传入.
以下是成果:
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
这一次,装饰器多了一层函数,可以具备接收外部参数(而不是被装饰器的函数的参数)功能,还是对同一个函数应用这个装饰器
@log_with_params('params')
def fun():
print('开始计时...')
time.sleep(3)
print('结束计时...')
return 123
再次执行函数:

可以看到外部传入给装饰器的参数已被内部接收到.,基本上大功告成.
但这里还有一个小问题
如果此时打印应用装饰器的函数名称:

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

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

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

注意这个装饰器使用时需要引入
from functools import wraps
最后以我自己的理解说一下什么是装饰器,对一些函数额外加上一些功能,但又不影响这些函数本身执行过程中定义的一些函数.
当然,类也可以⽤来构建装饰器,这个待笔者学会了再做分析探讨,欢迎大家批评指正

浙公网安备 33010602011771号