py之路——day12-20230521:装饰器

发布时间 2023-05-21 20:24:35作者: 投资交易大师

作者:zb

一、装饰器

1、装饰器的定义:

装饰器的“器”是函数的意思,即装饰器本质上是函数,用def关键字定义

2、装饰器的功能:

装饰其他函数,即为其他函数添加附加功能,为函数实现他们本身没有的功能

3、装饰器的原则:

⑴不能修改被装饰函数的源代码(有影响线上业务的风险)

⑵不能修改被装饰函数的调用方式

⑶装饰器对被装饰的函数来说应该是“透明”的

4、实现装饰器的知识储备:

⑴函数即变量:函数就是变量,函数名就是变量名就是一段内存空间的内存地址,函数体就是这段内存空间存储的数据

⑵高阶函数

⑶嵌套函数

高阶函数+嵌套函数就是装饰器!!!

二、装饰器之函数即变量

1、函数的定义和变量的定义是一样的

2、py的内存回收机制

当变量名(函数名)被删除后(例如使用del命令删除变量名),那么对应的这段内存空间就会被回收

3、匿名函数

⑴匿名函数的定义:

不定义函数名的函数就是匿名函数,定义匿名函数的关键字是“lamda”

⑵既然匿名函数是没有函数名的函数,那么匿名函数如何在内存中储存?

因为匿名函数没有函数名,因此会立刻被内存回收掉,因此需要给匿名函数定义一个变量名

示例代码如下:

 

1 a = lambda x: x * 3
2 
3 print(a(3))

 

 

 

执行结果:

 

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/1、匿名函数.py
2 9
3 
4 Process finished with exit code 0

 

4、函数即变量

定义一个函数,就是把函数体赋值给了函数名;函数和变量一样都有内存回收机制,没有了函数名的引用就一定会被回收掉;函数和变量一样,都是先定义后使用,定义没有先后顺序,只要是先定义好了就会保存在对应的内存空间中,然后按需使用即可

示例代码如下:

 1 def foo():
 2     """
 3 
 4     :return:
 5     """
 6     print('in the foo')
 7     bar()
 8 
 9 def bar():
10     """
11 
12     :return:
13     """
14     print('in the bar')
15 
16 foo()

 

执行结果:

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/2、函数的定义没有顺序之分.py
2 in the foo
3 in the bar
4 
5 Process finished with exit code 0

 

 

三、装饰器之高阶函数

1、高阶函数的定义:

⑴把一个函数名当做实参传递给另外一个函数,在不修改被装饰函数源代码的情况下为其添加附加功能

⑵返回值包含函数名(不修改被装饰函数的调用方式)

示例代码如下:

 

 1 def bar():
 2     """
 3 
 4     :return:
 5     """
 6     time.sleep(1)
 7     print('in the bar')
 8 
 9 def test2(func):
10     """
11 
12     :return:
13     """
14     print(func)
15     return func
16 
17 bar = test2(bar)
18 bar()   #高阶函数特点2,不改变源代码的调用方式

 

 

 

执行结果:

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/3、装饰器之高阶函数.py
2 <function bar at 0x00000222A352E9E0>
3 in the bar
4 
5 Process finished with exit code 0

 

四、装饰器之嵌套函数

1、嵌套函数的定义

在一个函数的函数体内用def关键字去声明一个函数,叫做函数的嵌套

示例代码如下:

 

 1 def foo():
 2     """
 3 
 4     :return:
 5     """
 6     print('in the foo')
 7     def bar():
 8         """
 9 
10         :return:
11         """
12         print("in the bar")
13     bar()
14 foo()

 

 

 

执行结果:

 

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/4、装饰器之函数嵌套.py
2 in the foo
3 in the bar
4 
5 Process finished with exit code 0

 

 

 

2、局部作用域和全局作用域的访问顺序

由内到外,类似于函数的局部变量和全局变量

示例代码如下:

 

 1 # 局部作用域和全局作用域的访问顺序
 2 x = 0
 3 def grandpa():
 4     x = 1
 5     def dad():
 6         x = 2
 7         def son():
 8             x = 3
 9             print(x)
10         son()
11     dad()
12 grandpa()

 

 

 

执行结果:

 

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/4、装饰器之函数嵌套.py
2 3
3 
4 Process finished with exit code 0

 

 

 

五、高阶装饰器

1、通用装饰器

示例代码如下:

 

 1 import time
 2 
 3 
 4 # 装饰器,高阶函数+嵌套函数=装饰器
 5 def timer(func):
 6     """
 7 
 8     :param func:
 9     :return:
10     """
11 
12     def deco(*args, **kwargs):
13         """
14 
15         :return:
16         """
17         start_time = time.time()
18         func(*args, **kwargs)
19         stop_time = time.time()
20         print("the func() run time is %s" % (stop_time - start_time))
21 
22     return deco
23 
24 
25 # 源代码
26 @timer
27 def test1():
28     """
29 
30     :return:
31     """
32     time.sleep(1)
33     print("in the test1")
34 
35 
36 @timer
37 def test2(name, age):
38     """
39 
40     :return:
41     """
42     time.sleep(1)
43     print("in the test2")
44     print("test2:", name, age)
45 
46 test1()
47 test2('zb', 32)

 

 

 

执行结果:

1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/5、通用装饰器.py
2 in the test1
3 the func() run time is 1.0112826824188232
4 in the test2
5 test2: zb 32
6 the func() run time is 1.0139482021331787
7 
8 Process finished with exit code 0

 

2、高阶装饰器

示例代码如下:

 

 1 # -*- coding:utf-8 -*-
 2 __author__ = "朱博"
 3 # 搞一个登录网页需要进行用户名和密码认证的装饰器
 4 user, passwd = 'zb', 'zb123'
 5 
 6 
 7 def auth(auth_type):
 8     print("auth func:", auth_type)
 9 
10     def outer_wrapper(func):
11         def wrapper(*args, **kwargs):
12             if auth_type == "local":
13                 print("wrapper args:", args, kwargs)
14                 username = input("请输入用户名:").strip()
15                 password = input("请输入密码:").strip()
16                 if username == user and password == passwd:
17                     print("\33[32;1m认证成功!\33[0m")
18                     res = func(*args, **kwargs)
19                     print("---after authentication---")
20                     return func()  # 下方的功能函数,其实就是这里的func函数,这里必须得有返回值,返回值才能打印出来
21                 else:
22                     print("\33[31;1m认证失败,程序退出!\33[0m")
23             elif auth_type == "ldap":
24                 print("不会。。。")
25 
26         return wrapper
27 
28     return outer_wrapper
29 
30 
31 # 网页登录功能
32 def index():
33     print("welcome to index page")
34 
35 
36 @auth(auth_type="local")  # 根据不同的认证方式去进行认证
37 def home():
38     print("welcome to home page")
39     # 给源代码函数增加一个返回值,看看是否可以打印
40     return "from home"
41 
42 
43 @auth(auth_type="ldap")
44 def bbs():
45     print("welcome to bbs page")
46 
47 
48 index()
49 print(home())  # 看看返回值是否可以打印?
50 bbs()   # wrapper

 

 

 

执行结果:

 

 1 D:\oldboy_py\venv\Scripts\python.exe D:/oldboy_py/day2-20230519装饰器/6、高级版装饰器.py
 2 auth func: local
 3 auth func: ldap
 4 welcome to index page
 5 wrapper args: () {}
 6 请输入用户名:zb
 7 请输入密码:zb123
 8 认证成功!
 9 welcome to home page
10 ---after authentication---
11 welcome to home page
12 from home
13 不会。。。
14 
15 Process finished with exit code 0