
1. 裝飾器的概念類比所謂的裝飾器, 其實就是一種概念上的比喻說法。這種說法認(rèn)為。給函數(shù)這個對象。穿上了一件。額外的外衣。我們來做一個假設(shè)。想象你手頭有一個函數(shù)存在。它就像一個自然人一樣。這個人具備完成特定任務(wù)的能力。舉個例子來說。這個人可以執(zhí)行計算兩個數(shù)值之和的操作。那么。裝飾器到底是干什么的。它的作用就像是給上述提到的人。強行添加一些輔助性的功能出來。比如在正式執(zhí)行加法運算之前。先對傳入的參數(shù)進(jìn)行合規(guī)性篩查。另外。也可能在運算結(jié)束以后。順手把所用時間記錄下來。從另一個角度來講, 那個裝飾器呀, 它是跟手機上的那個保護殼差不多的一個東西, 手機本身, 它就是一個函數(shù), 它有那些基本的功能存在, 比如說打電話和發(fā)短信這些東西都是它的功能, 那個保護殼作為裝飾器, 它可以給這部手機增加一些其他的新功能的, 像是防水啊防摔啊這種新功能的存在是不去改變手機本身所具備的那些打電話以及發(fā)短信的基本的功能的, 不過它確實是可以增強手機的那個整體的性能的。2. 簡單的裝飾器示例代碼解釋首先, 我們要去看一下一個最基礎(chǔ)的用來做裝飾的結(jié)構(gòu)是個什么樣子的。pythondef decorator_function(func):def wrapper():print(在函數(shù)執(zhí)行前做一些事情)func()print(在函數(shù)執(zhí)行后做一些事情)return wrapper在這里我們定義了一個名為空的函數(shù), 這個函數(shù)的名字是空白的, 它接收到了一個叫做func的作為參數(shù), 并且把這個叫func的當(dāng)作是這個函數(shù)自己的參數(shù)來處理, 而這個名稱為空白的這個函數(shù)部分呢, 我們就把它給稱為是我們的那個裝飾器。然后在裝飾器里面定義了一個新函數(shù), 這個新函數(shù)就像是為原來的那個 func 函數(shù)穿上了一件衣服。當(dāng)調(diào)用那個被修飾的函數(shù)的時候, 程序會先執(zhí)行打印出在函數(shù)執(zhí)行前做一些事情的這句代碼, 這個操作就是代表著向原本函數(shù)的流程里面添加了一個前置的動作或者說是額外加的功能, 緊接著再去運行func()這個原來的核心邏輯, 等到里面的主體部分都處理完了, 最后再去執(zhí)行打印出在函數(shù)執(zhí)行后做一些事情的這一句代碼, 這步就是在說原來函數(shù)跑完之后還要加上一個后置的處理環(huán)節(jié), 整個這一套流程就這么按順序地給過了一遍, 先事前準(zhǔn)備, 再處理核心事情, 最后是事后收尾。等到最后, 裝飾器返回函數(shù)這個對象。我們假設(shè)一下, 我們這里存在一個函數(shù), 這個函數(shù)的復(fù)雜度是比較簡單的。pythondef say_hello():print(Hello!)關(guān)于如何使用裝飾器來對這個函數(shù)進(jìn)行裝飾操作, 我們可以采取下面的這一種做法方式來完成任務(wù)。pythondecorated_say_hello decorator_function(say_hello)decorated_say_hello()首先第一步是把這個函數(shù)傳遞給裝飾器。然后返回的那個函數(shù)會被賦值給。最后再去調(diào)用()。這么一調(diào)用就會執(zhí)行函數(shù)。這就實現(xiàn)了在函數(shù)執(zhí)行之前和執(zhí)行之后去添加一些額外的功能。3. 語法糖形式的裝飾器解釋在實際使用的過程中, 還有一種更為簡潔的方式可以來使用裝飾器, 這種方式我們給它取了一個名字, 叫作語法糖。依據(jù)上面所展示的代碼內(nèi)容, 我們可以對其進(jìn)行如下的改寫操作:pythondecorator_functiondef say_hello():print(Hello!)這種使用了符號的寫法, 其意義其實就是等同于 ()這樣的形式。它可以讓代碼看上去更加簡潔一些。同時, 它也更符合現(xiàn)在大家習(xí)慣了的編程方式。4. 裝飾器的實際用途舉例日志記錄假設(shè)說你現(xiàn)在有一個函數(shù), 這個函數(shù)是用來處理用戶的訂單情況的, 你想要把這每一次去調(diào)用這個函數(shù)的具體時間記錄下來, 并且還想把這個函數(shù)里面的參數(shù)信息等東西也都保存下來。pythonimport timedef log_decorator(func):def wrapper(*args, kwargs):start_time time.time()print(f開始調(diào)用函數(shù) {func.__name__}參數(shù)為{args}和{kwargs})result func(*args, kwargs)end_time time.time()print(f函數(shù) {func.__name__} 執(zhí)行完成耗時{(end_time start_time)}秒)return resultreturn wrapperlog_decoratordef process_order(order_id, product_name):print(f正在處理訂單 {order_id}產(chǎn)品為{product_name})# 模擬訂單處理時間time.sleep(2)return 訂單處理成功在這里, 裝飾器這個東西是可以用來記錄函數(shù)在調(diào)用的時候所花費的時間以及所使用的參數(shù)等等相關(guān)信息的。并且, 當(dāng)去調(diào)用特定的這個函數(shù)的時候, 就會自動地去把裝飾器里面已經(jīng)寫好的那些代碼給執(zhí)行起來。這樣做呢, 就是在函數(shù)正式被執(zhí)行之前和之后這兩個階段里, 額外地加上一些專門用于記錄日志的功能操作。權(quán)限驗證如果你手頭有一個用于獲取用戶敏感信息的網(wǎng)頁應(yīng)用后端函數(shù), 那么你可能就需要去驗證這個用戶到底有沒有權(quán)限進(jìn)行訪問。pythondef permission_check_decorator(func):def wrapper(user):if user.has_permission():return func(user)else:print(用戶沒有權(quán)限訪問此功能)return wrapperclass User:def __init__(self, has_permission):self.has_permission has_permissionpermission_check_decoratordef get_user_info(user):print(獲取用戶信息)return 用戶的詳細(xì)信息在這個例子中裝飾器會檢查用戶對象user是否有訪問權(quán)限這一點是現(xiàn)在人們能直接看懂的普通話書面語, 如果有這個權(quán)限的話就執(zhí)行相關(guān)函數(shù)來獲取用戶信息, 如果沒有這個權(quán)限的話就打印提示信息, 這樣操作的目的就是為了通過裝飾器這一手段方便地給函數(shù)添加權(quán)限驗證的功能, 每個詞都要是現(xiàn)在常用的, 長句被切斷成了逗號分句。