一、叠加装饰器
在同一个被装饰对象中,添加多个装饰器,并执行
@装饰1
@装饰2
@装饰3
def 被装饰对象():
pass
注意:装饰器在调用被装饰对象时才会执行添加的功能
- 叠加装饰器
- 装饰的顺序:由下到上装饰
- 执行的顺序:由上往下
注意:无论inner中出现任何判断,最后都要返回调用后的被装饰对象
func(args, *kwargs)
# def wrapper(func):
# def inner(*args, **kwargs):
# # 注册
# res = func(*args, **kwargs)
# # 登录
# return res
#
# return inner
# 需求: 为被装饰对象,添加统计时间 与 登录认证功能
import time
user_info = {
'user': None
}
# 登录功能
def login():
# 判断用户没有登录时,执行
# 登录功能
# global user
username = input('请输入账号: ').strip()
password = input('请输入密码: ').strip()
with open('user.txt', 'r', encoding='utf-8') as f:
for line in f:
print(line)
name, pwd = line.strip('
').split(':') # [tank, 123]
if username == name and password == pwd:
print('登录成功!')
user_info['user'] = username
return True
else:
print('登录失败!')
return False
# 登录认证装饰器
def login_auth(func): # func---》 download_movie
def inner1(*args, **kwargs):
'''
注意: 无论inner中出现任何判断,
最后都要返回“调用后的被装饰对象” func(*args, **kwargs)
'''
# 登录认证
if user_info.get('user'):
# res = download_movie(*args, **kwargs)
res = func(*args, **kwargs)
return res
else:
flag = login()
# 添加用户是否登录判断
if flag:
res = func(*args, **kwargs)
return res
else:
login()
return func(*args, **kwargs)
return inner1
# 统计时间装饰器
def time_record(func):
def inner2(*args, **kwargs):
print('开始统计...')
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print(f'消耗时间为: {end_time - start_time}')
return res
return inner2
# 下载电影功能
'''
- 叠加装饰器:
- 装饰的顺序: 由下到上装饰
- 执行的顺序: 由上往下
'''
@time_record # inner2 = time_record(inner1地址)
@login_auth # inner1 = login_auth(download_movie)
def download_movie():
print('正在下载电影...')
time.sleep(2)
print('下载电影完成...')
return 'GTWZ.mp4'
# login()
# 执行的顺序: 先执行time_record功能,再执行login_auth功能
# 统计登录时间 + 下载时间
# download_movie()
# 装饰顺序
# @login_auth # inner1 = login_auth(inner2)
# @time_record # inner2 = time_record(download_movie)
# def download_movie():
# print('正在下载电影...')
# time.sleep(2)
# print('下载电影完成...')
# return 'GTWZ.mp4'
# 执行顺序:
# 先执行login_auth, 再执行time_record
# 只统计下载电影的时间
# login() # 先调用登录,模拟用户已登录
download_movie()
二、叠加装饰器详解
def wrapper1(func):
def inner1(*args, **kwargs):
print('1---start')
# 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner
# inner2
res = func(*args, **kwargs)
print('1---end')
return res
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print('2---start')
res = func(*args, **kwargs)
print('2---end')
return res
return inner2
def wrapper3(func):
def inner3(*args, **kwargs):
print('3---start')
res = func(*args, **kwargs)
print('3---end')
return res
return inner3
'''
叠加裝飾器的裝飾順序與執行順序:
- 裝飾順序: 调用wrapper装饰器拿到返回值inner
由下往上裝飾
- 執行順序: 调用装饰过后的返回值inner
由上往下執行
'''
@wrapper1 # index《---inner1 = wrapper1(inner2)
@wrapper2 # inner2 = wrapper2(inner3)
@wrapper3 # inner3 = wrapper3(index)
def index(): # 被裝飾對象 # inner1 ---》
print('from index...')
# 正在装饰
inner3 = wrapper3(index)
inner2 = wrapper2(inner3)
inner1 = wrapper1(inner2)
'''
inner1()
inner2()
inner3()
index()
'''
index() # 此处执行 # inner1() --> inner2() ---> inner3()
def wrapper1(func):
def inner1(*args, **kwargs):
print('1---start')
# 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner
# inner2
res = func(*args, **kwargs)
print('1---end')
return res
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print('2---start')
res = func(*args, **kwargs)
print('2---end')
return res
return inner2
def wrapper3(func):
def inner3(*args, **kwargs):
print('3---start')
res = func(*args, **kwargs)
print('3---end')
return res
return inner3
'''
叠加裝飾器的裝飾順序與執行順序:
- 裝飾順序: 调用wrapper装饰器拿到返回值inner
由下往上裝飾
- 執行順序: 调用装饰过后的返回值inner
由上往下執行
'''
@wrapper1 # index《---inner1 = wrapper1(inner2)
@wrapper2 # inner2 = wrapper2(inner3)
@wrapper3 # inner3 = wrapper3(index)
def index(): # 被裝飾對象 # inner1 ---》
print('from index...')
# 正在装饰
inner3 = wrapper3(index)
inner2 = wrapper2(inner3)
inner1 = wrapper1(inner2)
'''
inner1()
inner2()
inner3()
index()
'''
index() # 此处执行 # inner1() --> inner2() ---> inner3()