裝飾器本質上是乙個函式,該函式用來處理其他函式,它可以讓其他函式在不需要修改**的 前提下增加額外的功能,裝飾器的返回值也是乙個函式物件。它經常用於有切面需求的場景, 比如:插入日誌、效能測試、事務處理、快取、許可權校驗等應用場景。
為什麼需要裝飾器?
寫**要遵循 開放封閉 原則,雖然在這個原則是用的物件導向開發,但是也適用於函式式程式設計,簡單來說,它規定已經實現的功能**不允許被修改,但可以被擴充套件,即: 封閉:已實現的功能**塊 ,開放:對擴充套件開發
裝飾器具體可以實現以下功能:
引入日誌
函式執行時間統計
執行函式前預備處理
執行函式後清理功能
許可權校驗等場景
快取 接下來通過具體的案例看看裝飾器實現的功能,以及通過裝飾器裝飾不同型別函式的方法。
1)引入日誌的裝飾器
**如下:
import os
import time
import sys
# 裝飾器: 用來新增日誌資訊的
def add_log(fun):
# 獲取被裝飾的函式的返回值
result = fun(*args, **kwargs) # add(*args) ====> add(1, 2)
# 返回當前的字串格式時間
now_time = time.ctime()
# 獲取主機名 nodename='foundation0.ilt.example.com'
hostname = os.uname().nodename.split('.')[0]
# 執行的程式
process_full_name = sys.ar**[0]
process_name = os.path.split(process_full_name)[-1]
# 日誌內容
# info = "正在執行程式: " + str(fun)
# 獲取函式名: 函式名.__name__
info ="函式[%s]的執行結果為%s" %(fun.__name__, result)
log = " ".join([now_time, hostname, process_name, info])
print(log)
return result
@add_log # 語法糖====music = add_log(music)
def music():
time.sleep(1)
print("正在聽**.....")
@add_log
def add(x, y):
return x+y
通過上面的裝飾器,可以對後面的函式引入日誌。
2)函式執行時間統計
這裡需要匯入乙個關於時間的模組 time。
其中time.time()是乙個時間戳,返回的是從2023年到現在此時此刻經歷的秒數。這樣,在函式執行前加入time.time(),函式執行後再加乙個time.time(),然後用後面的值減去前面的值就是函式所執行的時間。
**如下:
import time
age = 19
def is_adult(fun):
start_time = time.time()
if age >= 18:
fun()
else:
print("未成年")
end_time = time.time()
# 返回的是函式的引用
@is_adult # 語法糖====music = is_adult(music)
def music():
time.sleep(1)
print("正在聽**.....")
@is_adult
def videos():
@is_adult
def game():
print("正在玩遊戲.....")
music()
執行結果:
3)多個裝飾器裝飾
在實際場景中,可能會遇到在不改變原來函式的基礎上增加多個內容,這時就需要用到多個裝飾器去進行裝飾。
下面這個案例加入了判斷使用者是否登入並且判斷使用者是否有許可權的裝飾器。
案例如下:
# 系統中的使用者資訊;
db = ,
'admin':
}# 儲存當前登入使用者的資訊;
login_user_session = {}
def is_login(fun):
"""判斷使用者是否登入, 如果沒有登入,先登入
"""if login_user_session:
result = fun(*args, **kwargs)
return result
else:
print("跳轉登入".center(50, '*'))
user = input("user: ")
passwd = input('password: ')
if user in db:
if db[user]['passwd'] == passwd:
login_user_session['username'] = user
print('登入成功')
# ***** 使用者登入成功, 執行刪除學生的操作;
result = fun(*args, **kwargs)
return result
else:
print("密碼錯誤")
else:
print("使用者不存在")
def is_permission(fun):
print("判斷是否有許可權......")
current_user = login_user_session.get('username')
permissson = db[current_user]['is_super']
if permissson == 1:
result = fun(*args, **kwargs)
return result
else:
print("使用者%s沒有許可權" % (current_user))
@is_login # delete = is_login(delete)
@is_permission
def delete():
return "正在刪除學生資訊"
result = delete()
print(result)
對上面案例進行分析,被裝飾的過程如下:
被呼叫的過程如下:
4)帶引數的裝飾器
如果裝飾器需要傳遞引數, 則在原有的裝飾器外面巢狀乙個函式即可。
**如下:
def auth(type):
if type=='local':
user = input("user:")
passwd = input("passwd:")
if user == 'root' and passwd == 'westos':
result = fun(*args, **kwargs)
return result
else:
print("使用者名稱/密碼錯誤")
else:
print("暫不支援遠端使用者登入")
@auth(type='remote')
def home():
print("這是主頁")
home()
我們可以總結出裝飾器的通用格式如下,一定要熟記:
def decorator(fun):# 在函式之前做的操作
res = fun(*args, **kwargs) # *args, **kwargs是實參, *args, **kwargs是在解包
# 在函式之後新增操作
return res
python裝飾器案例
計算函式的執行時間 import requests import time import re 黑名單 def filter url url 過濾url 測試網路請求的響應時間 def check runtime func print 初始裝飾 func.name 判斷url的 path路徑是否存在...
python裝飾器原理及相關操作
python裝飾器,簡單的說就是用於操作底層 的 在不改變底層 函式的情況下對底層 進行驗證操作等 def func print 歡迎光臨!print func func 列舉乙個簡單的web頁面呼叫例子 1 做登入驗證 2def login func 3print 登入成功 4return fun...
Python裝飾器原理分析和案例
裝飾器部分 裝飾器是可呼叫的物件,其引數是另乙個函式 被裝飾的函式 裝飾器可能會處理被裝飾的函式,將它返回 或者將其替換成另乙個函式或者可呼叫的物件。decorate def target print running target 以上例子,通過裝飾器之後,實際執行的是如下方法 def target...