裝飾器
1、疊加裝飾器
(1)什么是疊加裝飾器
在同一個被裝飾物件中,添加多個裝飾器并執行
(2)為什么要使用疊加裝飾器
不使用疊加裝飾器會導致代碼冗余,結構不清晰,可擴展性差,所以最好每一個新的功能都應該寫一個新的裝飾器
(3)怎么使用疊加裝飾器
使用方式:
@裝飾1
@裝飾2
@裝飾3
def 被裝飾物件():
pass
例子1:
我的需求:為被裝飾物件,添加統計與登錄認證功能
import time
user_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("\n").split(":")
name, pwd = info
if username == name and password == pwd:
print("登陸成功...")
user_info["user"] = username
else:
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 res
return inner1
def 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
"""
(2)有參裝飾器
有參裝飾器:在某些時候,需要給用戶的權限進行分類
"""
@wrapper1(引數1)
@wrapper2(引數2)
@wrapper3(引數3)
"""
例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 res
elif 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 wraps
def wrapper(func):
@wraps(func) # 修改名稱空間:inner ---> func
def inner(*args, **kwargs):
"""
這里是裝飾器
:param args:
:param kwargs:
:return:
"""
res = func(*args, **kwargs)
return res
return inner
def index():
"""
這里是被裝飾物件
:return:
"""
pass
print(index)
print(index.__doc__)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/168450.html
標籤:Python
上一篇:Python之裝飾器1
下一篇:Python之迭代器
