python装饰器
什么是装饰器?
装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象。
装饰器总是会比被装饰器先执行。
什么是一等对象?
- 可以把函数赋给变量
- 可以变成参数传递函数
- 函数里面可以定义函数
- 函数可以做为返回值返回(闭包)
装饰器代码示例
普通装饰器
1
2
3
4
5
6
7
8
9
10
11
12
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper
def greet():
print('hello world')
greet()带参数的装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def my_decorator(func):
def wrapper(message):
print('wrapper of decorator')
func(message)
return wrapper
def greet(message):
print(message)
greet('hello world')
# 输出
wrapper of decorator
hello world上面那种一般都会写成,这样写会比较灵活。
1
2
3
4
5
6
def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper带自定义参数的装饰器
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
def repeat(num):
def my_decorator(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
return my_decorator
def greet(message):
print(message)
greet('hello world')
# 输出:
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world类装饰器
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
class Count:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs)
def example():
print("hello world")
example()
# 输出
num of calls is: 1
hello world
example()
# 输出
num of calls is: 2
hello world类装饰器,要装饰的类必须实现__call__这个魔法函数。
装饰器的嵌套
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
import functools
def my_decorator1(func):
def wrapper(*args, **kwargs):
print('execute decorator1')
func(*args, **kwargs)
return wrapper
def my_decorator2(func):
def wrapper(*args, **kwargs):
print('execute decorator2')
func(*args, **kwargs)
return wrapper
def greet(message):
print(message)
greet('hello world')
# 输出
execute decorator1
execute decorator2
hello world异步的装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import pprint
import aiohttp
import datetime
import asyncio
def time_log(func):
async def wrap(*args, **kwargs):
print(f'现在时间:{datetime.datetime.now()},程序开始运行')
result = await func(*args, **kwargs)
print(f'现在时间:{datetime.datetime.now()},运行结束')
return result
return wrap
async def get(n):
async with aiohttp.ClientSession() as client:
resp = await client.get(f'http://httpbin.org/delay/{n}')
result = await resp.json()
pprint.pprint(result, indent=2)
asyncio.run(get(3))
当需要装饰异步函数时,装饰器也必须要为异步