python基础 14

发布时间 2023-05-30 20:25:07作者: 初学程序员

装饰器的简易版本

  核心思想:
    在不改变被装饰对象内部代码和原有调用方式的基础之上在添加额外的功能

# 给被装饰对象添加额外的功能
给index函数添加统计执行时间的功能
def index():
    time.sleep(3)
index()

import time


def index():
    time.sleep(3)
    print('from index')


def home():
    time.sleep(2)
    print('from home')


def func():
    time.sleep(2)
    print('from home')


def outer(func):
    # func = index
    def get_time():
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        func()  # index()
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))

    return get_time


# 利用闭包的形式来传参
# res = outer(index)  # res:get_time的内存地址
# res()  # get_time()

home = outer(home)
home()

解决参数的问题

 1 def index(name, username):
 2 time.sleep(3)
 3 print('from index')
 4 
 5 
 6 def home(name):
 7 time.sleep(2)
 8 print('from home', name)
 9 
10 
11 def outer(func):
12 # func = index
13 def get_time(*args, **kwargs):
14 # func:index
15 # 1. 在函数执行之前打一个时间点
16 start_time = time.time()
17 func(*args, **kwargs) # index() func('tony')
18 # 2. 在函数执行完毕之后在打一个时间点
19 end_time = time.time()
20 
21 # 3. 两个时间的差值就是函数的实际执行时间
22 print("函数执行了:%s秒" % (end_time - start_time))
23 
24 return get_time
25 index = outer(index)
26 index('tony', username='tank')

解决返回值问题

 1 def home(name):
 2     time.sleep(2)
 3     print('from home', name)
 4 
 5 def index():
 6     time.sleep(3)
 7     print('from index')
 8     return 'from index'
 9 
10 def outer(func):
11     # func = index
12     def get_time(*args, **kwargs):
13         # func:index
14         # 1. 在函数执行之前打一个时间点
15         start_time = time.time()
16         res=func(*args, **kwargs)  # index()  func('tony')
17         # 2. 在函数执行完毕之后在打一个时间点
18         end_time = time.time()
19 
20         # 3. 两个时间的差值就是函数的实际执行时间
21         print("函数执行了:%s秒" % (end_time - start_time))
22         return res
23     return get_time
24 index = outer(index)
25 res=index()
26 print(res)

课堂练习(登录认证功能)

 1 def home(name):
 2     print('from home')
 3 
 4 def func():
 5     print('from func')
 6 """
 7     必须登录之后才能执行index函数
 8         如果不登录不让执行
 9 """
10 def login_auth(func):
11     # func = index
12     def auth(*args, **kwargs):
13         # 写登录功能
14         # 1.
15         username = input('username:').strip()
16         password = input('password:').strip()
17 
18         # 2. 验证用户名和密码是否正确
19         if username == 'kevin' and password == '123':
20             print('登录成功')
21             res=func(*args, **kwargs)
22             return res
23         else:
24             print('用户名或者密码错误')
25     return auth
26 
27 home=login_auth(home)
28 home('kevin')

装饰器模板

 1 def outer(func):
 2     def inner(*args, **kwargs):
 3         print('这个是函数执行之前可以添加的功能')
 4         res = func(*args, **kwargs)
 5         print('这个是函数执行之后可以添加的功能')
 6         return res
 7 
 8     return inner
 9 
10 
11 def index():
12     print('from index')
13 
14 
15 index = outer(index)
16 index()

装饰器的语法糖

 1 def outer(func):
 2     def inner(*args, **kwargs):
 3         print('这个是函数执行之前可以添加的功能')
 4         res = func(*args, **kwargs)
 5         print('这个是函数执行之后可以添加的功能')
 6         return res
 7 
 8     return inner
 9 
10 
11 """装饰器本质就是函数,函数就是功能"""
12 # 语法糖
13 @outer  # index = outer(index)
14 def index():
15     print('from index')
16 
17 @outer  # home=outer(home)  -----------> home是outer函数的返回值(内部函数的函数名)
18 def home():
19     print('from home')
20 
21 home() # inner()
22 # index = outer(index)
23 index()
24 
25 # home = outer(home)
26 # home()
27 """
28 语法糖的书写规范:
29     紧贴着被装饰对象的上方写
30 语法糖的内部原理:
31     他会自定把被装饰对象的名字当成参数传给装饰器函数调用
32 """
33 @outer  # func = outer(func)
34 def func():
35     print('from func')
36     
37 func()  # inner()

双层语法糖

 1 # 判断七句print执行顺序
 2 def outter1(func1):
 3     print('加载了outter1')
 4     def wrapper1(*args, **kwargs):
 5         print('执行了wrapper1')
 6         res1 = func1(*args, **kwargs)
 7         return res1
 8     return wrapper1
 9 
10 def outter2(func2):
11     print('加载了outter2')
12     def wrapper2(*args, **kwargs):
13         print('执行了wrapper2')
14         res2 = func2(*args, **kwargs)
15         return res2
16     return wrapper2
17 
18 def outter3(func3):
19     print('加载了outter3')
20     def wrapper3(*args, **kwargs):
21         print('执行了wrapper3')
22         res3 = func3(*args, **kwargs)
23         return res3
24     return wrapper3
25 
26 
27 @outter1
28 @outter2
29 @outter3
30 def index():
31     print('from index')

多认证登录功能

 1 def login_auth(func):
 2     # func = index
 3     def auth(*args, **kwargs):
 4         # 判断用户是否登录了
 5         if is_login.get('is_login'):
 6             # 正常执行函数
 7             res = func(*args, **kwargs)
 8             return res
 9         # 写登录功能
10         # 1.
11         username = input('username:').strip()
12         password = input('password:').strip()
13 
14         # 2. 验证用户名和密码是否正确
15         if username == 'kevin' and password == '123':
16             print('登录成功')
17             res = func(*args, **kwargs)
18             is_login['is_login'] = True
19             return res
20         else:
21             print('用户名或者密码错误')
22 
23     return auth
24 
25 
26 @login_auth
27 def index():
28     print('from index')
29 
30 
31 @login_auth
32 def home():
33     print('from home')
34 
35 
36 index()
37 home()

装饰器的修复技术了解

from functools import wraps

def outer(func):
    # func = index
    @wraps(func)
    def get_time(*args, **kwargs):
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        res = func(*args, **kwargs)  # index()  func('tony')
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))
        return res

    return get_time

有参装饰器

 1 # 有参装饰器就是带参数的装饰器
 2 # 先前我们学习的装饰器就是无参装饰器:不到参数的装饰器
 3 
 4 def outter(type):
 5     # type = 1
 6     def login_auth(func):
 7         # func = index
 8         def auth(*args, **kwargs):
 9             # 写登录功能
10             # 1.
11             username = input('username:').strip()
12             password = input('password:').strip()
13 
14             # 2. 验证用户名和密码是否正确
15             # with open('')
16             """
17                 根据不同的参数用户名和密码来自于不同的位置
18             """
19             if type == 'file':
20                 print('用户名和密码来自于文件')
21             elif type == 'mysql':
22                 print('用户名和密码来自于MySQL')
23             elif type == 'oracle':
24                 print('用户名和密码来自于Oracle')
25 
26             # if username == 'kevin' and password == '123':
27             #     print('登录成功')
28             #     res = func(*args, **kwargs)
29             #     return res
30             # else:
31             #     print('用户名或者密码错误')
32 
33         return auth
34     return login_auth
35 # @login_auth  # 如果是index函数认证,用户名和密码来自于文件  login_auth(index, 1)
36 @outter('file') # @login_auth     # 如果是index函数认证,用户名和密码来自于文件  login_auth(index, 1)
37 def index():
38     print('from index')
39 
40 index()
41 
42 # @login_auth  # 如果是home函数认证,用户名和密码来MySQL
43 @outter('mysql')  # 如果是home函数认证,用户名和密码来MySQL
44 def home():
45     print('from home')
46 
47 home()
48 
49 @outter('oracle')  # 如果是func函数认证,用户名和密码来oracle
50 def func():
51     print('from func')
52 
53 func()