python装饰器
装饰器,在不改变原函数的情况下,为其增强功能。
1. 前置知识
高阶函数
在python中函数也是被视为对象的,可以作为参数传递
示例1
1 2 3 4 5 6 7 8 9 10 11
| def square(n): return n * n
def func(a, b, fun): res = fun(a) + fun(b) return res
print(func(2, 3, square))
|
示例2
1 2 3 4 5 6 7 8 9 10 11 12
| 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))
|
闭包函数
声明在一个函数种的函数被称为闭包函数,它可以访问其所在外部函数的参数和变量。
1 2 3 4 5 6 7 8 9 10
| def outer(): x = 5 def inner(): print(x) return inner
outer()
|
2、简单的装饰器示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import time
def calc_spend_time(func): ''' description: 一个监测程序运行的装饰器函数。在不改动原业务函数的情况下,增添其功能。 输入一个函数,即参数为业务函数 返回一个函数,即新建的内部闭包函数(装饰过的函数) ''' def wrapper(): start = time.time() func() print(f'{func} is called') print(func.__name__ + '() start') end = time.time() print('用时{:.5f}秒'.format(end-start)) return wrapper
@calc_spend_time
def hello(): print('hello world!')
if __name__ == '__main__': hello()
|
3. 业务函数带参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 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
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
用来发送一个非键值对的可变数量的参数列表给一个函数,可看作tuple
参数**kwargs
允许你将不定长度的键值对作为参数传递给一个函数,可看作dict
4. 装饰器带参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| 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
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)
|