老男孩python DAY12笔记

1. 主要内容

- args和*args的区别

- 装饰器进阶

  • functools wraps
  • 带参数的装饰器
  • 多个装饰器装饰同一个参数

2. args和*args的区别

1
2
3
4
5
6
7
8
9
def outer(*args):
print(args) # (1, 2, 3, 4)元组形式
print(*args) # 打散 1, 2, 3, 4

def inner(*args):
print('inner: ', args) # inner: (1, 2, 3, 4)
inner(*args) # inner(1,2,3,4)

outer(1, 2, 3, 4)

3. functools wraps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from functools import wraps


def wrapper(func):
@wraps(func) # warps 带参数的装饰器,
def inner(*args, **kwargs):
print('在被装饰的函数执行之前做的事')
ret = func(*args, **kwargs)
print('在被装饰的函数执行之后做的事')
return ret
return inner

@wrapper # holiday = wrapper(holiday)
def holiday(day):
'''这是一个放假通知'''
print('全体放假%s天' % day)
return '好开心'

print(holiday.__name__)
print(holiday.__doc__) #打印函数注释文档,如果没有wraps,打印的是wrapper的注释,因此会返回None
ret = holiday(3)
print(ret)

4. 带参数的装饰器

如果有很多函数都装载了装饰器,想要取消需要一个一个的停掉,这样很麻烦。因此可以用带参数的装饰器,设置flag来解决

无参数的装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import time


def timmer(func):
def inner(*args, **kwargs):
start = time.time()
ret = func(*args, **kwargs)
end = time.time()
print(end - start)
return ret
return inner


@timmer
def wahaha():
time.sleep(0.1)
print('wahhhh')

@timmer
def erguotou():
time.sleep(0.1)
print('erguotou')

带参数的装饰器
(在装饰器函数外面又套了一个函数,利用闭包原理用外层函数向内部传递参数)

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
35
36
import time

flag = False


def timmer_out(flag):

def timmer(func):

def inner(*args, **kwargs):
if flag:
start = time.time()
ret = func(*args, **kwargs)
end = time.time()
print(end - start)
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner
return timmer

# timmer = timmer_out(flag)
# @timmer
@timmer_out(flag)
def wahaha():
time.sleep(0.1)
print('wahhhh')

@timmer_out(flag)
def erguotou():
time.sleep(0.1)
print('erguotou')

wahaha()
erguotou()

5. 多个装饰器装饰同一个函数

由于装饰器会寻找最接近的函数,因此出现“外侧套内侧的现象”

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 wrapper1(func):
def inner1():
print('wrapper1, before func')
func()
print('wrapper1, after func')
return inner1


def wrapper2(func):
def inner2():
print('wrapper2, before func')
func()
print('wrapper2, after func')
return inner2


@wrapper2 # f = wrapper2(f)--------->wrapper2(inner1)-----> inner2
@wrapper1 # f = wrapper1(f) === inner1
def f():
print('in f')


f() # inner2()


'''
wrapper2, before func
wrapper1, before func
in f
wrapper1, after func
wrapper2, after func
'''

命令执行顺序如下: