python中的闭包和修饰器

学习:https://www.bilibili.com/video/BV1JW411i7HR?from=search&seid=16657644362313549009

一、闭包demo1

闭包概念:内部函数对【外部函数作用域里的变量】的引用

1.现在函数ouFunc()内部有一个函数innerFunc(),代码如下:

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: bibao1.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 12:36
 8 @version: Python 3.7.8
 9 '''
10 
11 """
12 闭包:内部函数对[外部函数作用域里变量]的引用
13 
14 """
15 
16 
17 def outFunc():
18     print('this is outFunc')
19     def innerFunc():
20         print('this is innerFunc')
21 
22 outFunc()
23 innerFunc()
View Code

执行结果:innerFunc未定义,因此不能再外面直接调用innerFunc函数。

innerFunc()内部函数只有在外部函数outFunc()执行过程中才能被创建,当outFunc()的生命周期结束,则innerFunc()也被销毁

 

 

 

2.将内部函数返回(保持)给一个变量,然后在外部调用这个变量,且在后面加上括号。

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: bibao1.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 12:36
 8 @version: Python 3.7.8
 9 '''
10 
11 """
12 闭包:内部函数对[外部函数作用域里变量]的引用
13 
14 """
15 
16 def outFunc():
17     print('this is outFunc')
18     def innerFunc():
19         print('this is innerFunc')
20     return innerFunc
21 
22 v1 = outFunc()
23 v1()
View Code

 

 

 

3.外部函数内定义内部变量a,内部函数定义参数Num

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: bibao1.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 12:36
 8 @version: Python 3.7.8
 9 '''
10 
11 """
12 闭包:内部函数对[外部函数作用域里变量]的引用
13 
14 """
15 
16 
17 def outFunc():
18     print('this is outFunc')
19     a = 1
20 
21     def innerFunc(num):
22         print('this is innerFunc')
23         print(num + a)
24 
25     return innerFunc
26 
27 
28 v1 = outFunc()
29 v1(3)
View Code

 

 

 返回值是 3+1 = 4.

因此,闭包:内部函数对【外部函数作用域里的变量】的引用。就说明这是一个闭包。

闭包内的闭包函数是innerFunc(num),私有化了外部函数outFunc()内的变量a,完成了数据的封装。

 

4.demo2

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: bibao1.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 12:36
 8 @version: Python 3.7.8
 9 '''
10 
11 """
12 闭包:内部函数对[外部函数作用域里变量]的引用
13 
14 """
15 
16 
17 def outFunc():
18     print('this is outFunc')
19     a = 1
20 
21     def innerFunc(num):
22         print('this is innerFunc')
23         print(num + a)
24 
25     return innerFunc
26 
27 
28 v1 = outFunc()
29 v1(3)
30 
31 mylist = [1,2,3,4,5]
32 
33 def func1(obj):
34     print('func1:',obj)
35     def func2():
36         obj[0]+=1
37         print('func2:',obj)
38     return func2
39 
40 v2 = func1(mylist)
41 v2()
42 v2()
43 v2()
44 del v2
View Code

 

 

 v2就是一个闭包,将mylist保存下来,且还可以对mylist进行多次更改,只有当del v2后,mylist就不存在了。

 

二、装饰器,又叫语法糖@,通过闭包原理实现装饰器

装饰器不影响原来的函数的功能,只能在原函数上新增新的功能。

装饰器和闭包的区别在于:

装饰器中内部函数也有返回,返回的是函数调用。

闭包中内部函数没有返回值,只有外部函数有返回值

 

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: zsq1.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 13:31
 8 @version: Python 3.7.8
 9 '''
10 
11 
12 def func1(func):  # 外部闭包函数的参数是被装饰的函数对象func
13     def func2():
14         print("new function")
15         return func()  # 返回外部函数的参数
16 
17     return func2
18 
19 
20 @func1
21 def myprint():
22     print("this is print1")
23 
24 
25 def myprint2():
26     print("this is print2")
27 
28 
29 myprint()
30 # myprint() 等于执行 func1(myprint)()
31 func1(myprint2)()
32 # func1(myprint2)() 等于@func1的效果
View Code

 

 

 

三、装饰器带参数:

 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: param_zsq.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 14:13
 8 @version: Python 3.7.8
 9 '''
10 
11 # 第一层是装饰器的参数
12 def arg_func(sex, old):
13     # 第二层函数是用来调用被装饰函数
14     def func1(func):
15         # 第三层是装饰器内部封装的内容
16         def func2():
17             if sex == 'man':
18                 print("男人不能生孩子")
19             if sex == 'woman' and old < 18:
20                 print("女人未到18岁,不可以生孩子")
21             if sex == 'woman' and old > 50:
22                 print("女人岁数太大,不可以生孩子")
23             if sex == 'woman' and (old >= 18 and old <= 50):
24                 print("女人岁数刚好,可以生孩子")
25             return func()
26         return func2
27 
28     return func1
29 
30 
31 @arg_func(sex='man', old=18)
32 def man():
33     print('努力工作!')
34 
35 
36 @arg_func(sex='woman', old=35)
37 def woman():
38     print('努力工作!')
39 
40 
41 man()
42 woman()
43 
44 def woman1():
45     print('woman1 努力工作!')
46 
47 arg_func(sex='woman',old=38)(woman1)()
View Code

 

 

四、被装饰函数带参数

被装饰函数带参数,如果想对参数做更改,需要将被装饰函数的参数放在装饰器最内层的函数中
 1 '''
 2 @author:invoker
 3 @project:fastApiStudy
 4 @file: b_func_param.py
 5 @contact:invoker2021@126.com
 6 @descript:
 7 @Date:2021/8/5 15:14
 8 @version: Python 3.7.8
 9 '''
10 
11 
12 # 被装饰函数带参数,如果想对参数做更改,需要将被装饰函数的参数放在装饰器最内层的函数中
13 def func1(func):
14     def func2(x, y):
15         x += 2
16         y += 3
17         return func(x, y)
18 
19     return func2
20 
21 
22 @func1
23 def mysum(a, b):
24     print(a + b)
25 
26 
27 mysum(1, 2)
28 
29 
30 def mysum2(a, b):
31     print(a + b)
32 
33 
34 func1(mysum2)(1, 2)
View Code

 

 

综合三,四,装饰器的参数在最外层,被装饰的参数在最内层,中间层则是被装饰的函数

 

posted @ 2021-08-05 15:20  kaer_invoker  阅读(95)  评论(0编辑  收藏  举报