Python“三大器”之装饰器2
装饰器
1、叠加装饰器
(1)什么是叠加装饰器
在同一个被装饰对象中,添加多个装饰器并执行
(2)为什么要使用叠加装饰器
不使用叠加装饰器会导致代码冗余,结构不清晰,可扩展性差,所以最好每一个新的功能都应该写一个新的装饰器
(3)怎么使用叠加装饰器
使用方式:
@装饰1
@装饰2
@装饰3
def 被装饰对象():
pass
例子1:
我的需求:为被装饰对象,添加统计与登录认证功能
import timeuser_info
= {"user": None}
# 登陆功能def login():
username
= input("请输入您的账户:").strip()password
= input("请输入您的密码:").strip()with open(
"dir/passwd.txt", "r", encoding="utf-8") as f: # 我在同级目录下创建了一个dir目录,然后在目录下创建了一个passwd的文本文档,里面内容为tank:123,然后回车另起一行保存info
= f.readline().strip("").split(":")name, pwd
= infoif username == name and password == pwd:print("登陆成功...")user_info[
"user"] = usernameelse:print("登录失败...")# 登录认证装饰器def login_auth(func):
def inner1(*args, **kwargs):
# 登录认证功能
if user_info.get("user"):
res = func(*args, **kwargs)
return res
else:
login()
return func(*args, **kwargs) # 无论inner1中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)
return inner1
##### 注意:登陆这里无论inner1中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)
# 统计时间装饰器
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,再装饰login_auth
@login_auth # inner1 = login_auth(inner2)
@time_record # inner2 = time_record(download_movie)
def download_movie():
print("电影开始下载...")
time.sleep(3)
print("电影下载完成!")
return"gtwz.mp4"
# 执行顺序:先执行login_auth,再执行time_record
# 只统计下载电影的时间
login() # 先调用用户登录,模拟用户已登录
download_movie()
注意:装饰器在调用被装饰对象时才会执行添加的功能
装饰的顺序:由下到上
执行的顺序:由上到下
附上图解:
例子2:通过例子看到执行过程:
def wrapper1(func1):def inner1(*args, **kwargs):print("1-----start")# 被装饰对象在调用时,如果还有其他装饰器,会先执行其他装饰器中的inner# 下一步执行inner2
res = func1(*args, **kwargs)
print("1-----end")return resreturn inner1def wrapper2(func2):def inner2(*args, **kwargs):print("2-----start")# 被装饰对象在调用时,如果还有其他装饰器,会先执行其他装饰器中的inner# 下一步执行inner3
res = func2(*args, **kwargs)
print("2-----end")
return res
return inner2
def wrapper3(func3):
def inner3(*args, **kwargs):
print("3-----start")
# 被装饰对象在调用时,没有其他装饰器
# 下一步执行index
res = func3(*args, **kwargs)
print("3-----end")
return res
return inner3
@wrapper1 # inner1 = wrapper1(inner2)
@wrapper2 # inner2 = wrapper2(inner3)
@wrapper3 # inner3 = wrapper3(index)
# 被装饰对象
def index():
print("hello")
"""
装饰顺序:
从下到上
执行顺序:
从上到下
本例子的执行顺序:
inner1()
inner2()
inner3()
index()
inner3的res
inner2的res
inner1的res
"""
2、无参装饰器和有参装饰器
(1)无参装饰器
在被装饰对象装饰时,没有传参数的装饰器
@wrapper1
@wrapper2
@wrapper3
无参装饰器模板:
# 无参装饰器模板:def wrapper(func):
def inner(*args, **kwargs):
# 添加代码块功能
res = func(*args, **kwargs)
# 添加代码块功能
return res
return inner
(2)有参装饰器
有参装饰器:在某些时候,需要给用户的权限进行分类
@wrapper1(参数1)
@wrapper2(参数2)
@wrapper3(参数3)
有参装饰器模板:
# 有参装饰器模板:def outer(para): # 传入的para参数是用在inner()内部函数使用
def wrapper(func):
def inner(*args, **kwargs):
if para == "": # 功能1
# 添加调用前的功能代码块1
res = func(*args, **kwargs)
# 添加调用后的功能代码块1
return res
elif para == "": # 功能2
# 添加调用前的功能代码块2
res = func(*args, **kwargs)
# 添加调用后的功能代码块2
return res
else: # 功能3
# 添加调用前的功能代码块3
res = func(*args, **kwargs)
# 添加调用后的功能代码块3
return res
# 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)
return inner
return wrapper
例1:可通过传参查看用户权限/功能
def user_auth(user_role):def wrapper(func):def inner(*args, **kwargs):if user_role == "SVIP":# 添加svip的权限/功能print(user_role)
res
= func(*args, **kwargs)return reselif user_role == "VIP":# 添加vip的权限/功能print(user_role)
res = func(*args, **kwargs)
return res
return inner
return wrapper
@user_auth("VIP")
def index():
pass
index()
3、wraps修复(了解)
wraps是一个修复工具,修复的是被装饰对象的空间
functools import wrapsdef wrapper(func):@wraps(func)
# 修改名称空间:inner ---> funcdef inner(*args, **kwargs):
"""这里是装饰器
:param args:
:param kwargs:
:return:
"""res
= func(*args, **kwargs)return resreturn innerdef index():"""这里是被装饰对象
:return:
"""pass
print(index)
print(index.__doc__)
以上是 Python“三大器”之装饰器2 的全部内容, 来源链接: utcz.com/z/530937.html