Python装饰器
# python装饰器
装饰器,在不改变原函数的情况下,为其增强功能。
# 1. 前置知识
# 高阶函数
在python中函数也是被视为对象的,可以作为参数传递
# 示例1
def square(n):
return n * n
def func(a, b, fun):
res = fun(a) + fun(b)
return res
print(func(2, 3, square)) # 函数square作为函数传入到函数func中
# 结果:13
# 示例2
def add(a, b):
return a + b
def sub(a, b):
return a - b
funcs = [add, sub] # 函数作为列表成员方便调用
print(funcs[0](1, 2))
print(funcs[1](1, 2))
# 结果:3,-1
# 闭包函数
声明在一个函数种的函数被称为闭包函数,它可以访问其所在外部函数的参数和变量。
def outer():
x = 5
def inner():
print(x)
return inner
outer()
# 结果是 5 ,内部函数inner引用外部函数的变量
# inner()函数就是一个闭包
# 2、简单的装饰器示例
import time
def calc_spend_time(func):
'''
description:
一个监测程序运行的装饰器函数。在不改动原业务函数的情况下,增添其功能。
输入一个函数,即参数为业务函数
返回一个函数,即新建的内部闭包函数(装饰过的函数)
'''
def wrapper():
# 调用前的操作
start = time.time()
# 调用业务函数
func()
# 调用后的操作
print(f'{func} is called')
print(func.__name__+' is called')
print(func.__name__ + '() start')
end = time.time()
print('用时{:.5f}秒'.format(end-start))
return wrapper #返回装饰后的闭包函数
@calc_spend_time # 语法糖,相当于hello = decorator(hello)
def hello():
print('hello world!')
if __name__ == '__main__':
hello()
# hello world!
# <function hello at 0x01F2ED18> is called
# hello is called
# hello() start
# 用时0.00099秒
# 3. 业务函数带参数
def decorator(func):
'''
description: 记录日志的装饰器函数。
'''
def wrapper(*args, **kwargs):
'''
业务函数的参数通过wrapper的函数来传递
返回值通过wrapper的返回值返回
'''
value = func(*args, **kwargs) # 记录业务函数返回值
print(f'{func} is called with arguments = {args} and kwargs = {kwargs}')
print(f'{func} return value {value}')
return value # 返回业务函数的返回值
return wrapper
@decorator # 语法糖,相当于hello = decorator(hello)
def func1(*args, **kwargs):
sum = 0
for num in args:
sum += num
print(f'args = {args}, kwargs = {kwargs}')
return sum
if __name__ == '__main__':
func1(1, 2, c=3, d=4)
# args = (1, 2), kwargs = {'c': 3, 'd': 4}
# <function func1 at 0x013DED18> is called with arguments = (1, 2) and kwargs = {'c': 3, 'd': 4}
# <function func1 at 0x013DED18> return value 3
参数*args用来发送一个非键值对的可变数量的参数列表给一个函数,可看作tuple
参数**kwargs允许你将不定长度的键值对作为参数传递给一个函数,可看作dict
# 4. 装饰器带参数
def outer(author): # 再套一层,传入装饰器的参数
def middle(func): # 中间层传入业务函数
def wrapper(*args, **kwargs):
value = func(*args, **kwargs) # 记录业务函数返回值
print('author: ', author,
f'\n{func} is called with arguments = {args} and kwargs = {kwargs}',
f'\nreturn value: {value}')
return value # 返回业务函数的返回值
return wrapper
return middle
# @outer('lei') # 语法糖,相当于func1 = outer('lei')(func1)
def func1(*args, **kwargs):
sum = 0
for num in args:
sum += num
return sum
if __name__ == '__main__':
func1 = outer('lei')(func1)
func1(1, 2, c=3, d=4)
# # 不用语法糖等价1:
# func1 = outer('lei')(func1)
# func1(1, 2, c=3, d=4)
# # 不用语法糖等价2:
# func1 = outer('lei')(func1)(1, 2, c=3, d=4)
# 输出结果:
# author: lei
# <function func1 at 0x0192EE38> is called with arguments = (1, 2) and kwargs = {'c': 3, 'd': 4}
# return value: 3
上次更新: 2022/11/24, 22:50:32