一、闭包
1、外层函数嵌套内层函数,在内层函数中使用外层函数的局部变量
2、局部变量和内层函数统称为闭包
3、内层函数为闭包函数
闭包函数访问外层函数的局部变量时,访问的总是该变量的最新值
1 def outer():
2 x = 10 # 外层函数的局部变量
3 def inner():
4 nonlocal x # 关键字标记 变量x 是外层函数的局部变量
5 x += 1
6 return x
7 return inner
8
9 r1 = outer() # r1 --> 函数地址(内层函数)
10
11 print(r1()) # 11
12 print(r1()) # 12
13 print(r1()) # 13
14
15 r = outer()
16 print(r) # <function outer.<locals>.inner at 0x0000000003C7B9D8>
17 print(r()) # 11 此时才是调用inner()函数的调用处
二、装饰器
闭包的应用,对于已经实现定义好了的函数功能,在不改变原函数的情况下,给其新增功能
1 def outer(func): # 外层函数的参数: 函数 --> 指的就是要装饰的函数
2
3 def inner():
4 print("此处代码在被装饰的函数执行之前执行")
5 func()
6 print("此处代码在被装饰的函数执行之后执行")
7 return inner
8
9 @outer
10 def func():
11 print("---嘻嘻哈哈---")
12
13 func()
14 """
15 此处代码在被装饰的函数执行之前执行
16 ---嘻嘻哈哈---
17 此处代码在被装饰的函数执行之后执行
18 """
1 import time
2
3 def get_time(func): # 装饰器--> 装饰的是函数
4
5 def inner():
6 before = time.time() # 函数执行之前的时间戳
7 func()
8 after = time.time() # 函数执行结束之后的时间戳
9 print("函数执行时间", after - before) # 返回值为时间戳的差值
10 return inner
11
12 @get_time
13 def get_num():
14 for x in range(100):
15 print(x)
16
17 get_num()
18 """
19 0
20 1
21 ...
22 98
23 99
24 函数执行时间 0.0010001659393310547
25 """
三、装饰一个带有返回值的函数
1 def outer(func):
2
3 def inner():
4 print("调用前执行")
5 res = func() # 此时接收原函数的返回值
6 print("调用后执行")
7 return res
8 return inner
9
10 @outer
11 def say():
12 print("我是一个say函数")
13
14 say()
15 """
16 调用前执行
17 我是一个say函数
18 调用后执行
19 """
20
21 @outer
22 def say2():
23 return "我是一个say2函数"
24
25 res = say2()
26 # 被装饰的函数say2()--> 调用的是装饰器的inner()函数 --> res = inner()
27 print(res)
28 """
29 调用前执行
30 调用后执行
31 我是一个say2函数
32 """
四、装饰带有参数的函数
1 def outer(func):
2
3 def inner(x): # 形参: 被装饰的函数的形参
4 print("调用前执行")
5 func(x)
6 print("调用后执行")
7 return inner
8
9 @outer
10 def get_num(a):
11 print(a * 10)
12
13 get_num(2) # 被装饰后的函数 --> inner(2)
14 """
15 调用前执行
16 20
17 调用后执行
18 """
1 def outer(func):
2
3 def inner(*args, **kwargs):
4 print("调用前执行")
5 func(*args, **kwargs)
6 print("调用后执行")
7 return inner
8
9 @outer
10 def get_num(*args, **kwargs):
11 print(args)
12 print(kwargs)
13
14 get_num(1,2,3,4, xixi="haha", 年龄=7.5)
15
16 """
17 调用前执行
18 (1, 2, 3, 4)
19 {'xixi': 'haha', '年龄': 7.5}
20 调用后执行
21 """
五、多个装饰器
1 def outer1(func):
2 def inner():
3 print("装饰1调用前")
4 func()
5 print("装饰1调用后")
6 return inner
7
8 def outer2(func):
9 def inner():
10 print("装饰2调用前")
11 func()
12 print("装饰2调用后")
13 return inner
14
15 @outer2
16 @outer1
17 def study():
18 print("xixihaha")
19
20 study()
21 """
22 装饰2调用前
23 装饰1调用前
24 xixihaha
25 装饰1调用后
26 装饰2调用后
27 """
六、查看被装饰函数的文档注释
1、需要导入 from functools import wraps
2、 装饰内层函数 @wraps(被装饰的函数)
1 from functools import wraps
2
3 def outer(func):
4 @wraps(func) # 解决不能查看文档注释的问题
5 def inner():
6 func()
7 return inner
8
9 @outer
10 def func():
11 """
12 func函数
13 :return: 无
14 """
15 print("xixi")
16
17 print(func.__doc__)
18 """
19 func函数
20 :return: 无
21 """