網站首頁 編程語言 正文
裝飾器簡介
裝飾器(decorator)是一種高級Python語法。可以對一個函數、方法或者類進行加工。在Python中,我們有多種方法對函數和類進行加工,相對于其它方式,裝飾器語法簡單,代碼可讀性高。因此,裝飾器在Python項目中有廣泛的應用。修飾器經常被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理, Web權限校驗, Cache等。
裝飾器的優點是能夠抽離出大量函數中與函數功能本身無關的雷同代碼并繼續重用。即,可以將函數“修飾”為完全不同的行為,可以有效的將業務邏輯正交分解。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。例如記錄日志,需要對某些函數進行記錄。笨的辦法,每個函數加入代碼,如果代碼變了,就悲催了。裝飾器的辦法,定義一個專門日志記錄的裝飾器,對需要的函數進行裝飾。
基礎通用裝飾器
源碼示例
def wrapper_out(func):
print('-- wrapper_out start --')
def inner(*args, **kwargs):
print("-- inner start --")
ret = func(*args, **kwargs)
print("-- inner end --")
return ret
print('-- wrapper_out end --')
return inner
@wrapper_out
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
執行結果
-- wrapper_out start --
-- wrapper_out end --
>>>>>>>>>>>>>>
-- inner start --
--test--
-- inner end --
2
帶參數裝飾器
源碼示例
def wrapper_out(mode=None):
print('-- wrapper_out start --')
def inner_1(func):
print("-- inner_1 start --")
def inner_2(*args, **kwargs):
print("-- inner_2 start --")
print(f"mode: {mode}")
ret = func(*args, **kwargs)
print("-- inner_2 end --")
return ret
print("-- inner_2 end --")
return inner_2
print('-- wrapper_out end --')
return inner_1
@wrapper_out(mode=2)
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
源碼結果
-- wrapper_out start --
-- wrapper_out end --
-- inner_1 start --
-- inner_2 end --
>>>>>>>>>>>>>>
-- inner_2 start --
mode: 2
--test--
-- inner_2 end --
2
源碼解析
帶參數的裝飾器函數, 需要多嵌套一層, 外層裝飾器的參數
預加載的時候已經是根據函數的編寫順序進行加載
執行順序在對應的最內存函數中調用最外層的裝飾器函數參數
被裝飾函數是最為 inner_1 的參數進行傳入, 被裝飾函數的參數是作為 inner_2 的參數傳入
被裝飾函數的執行位置是在 inner_2 中, 使用inner_1 的參數變量和 inner_2 的參數變量共同協助下進行執行
同時還要使用裝飾器函數 wrapper_out 的參數變量進行額外的操作
多裝飾器執行順序
源碼示例
def wrapper_out1(func):
print('-- wrapper_out_1 start --')
def inner1(*args, **kwargs):
print("-- inner_1 start --")
ret = func(*args, **kwargs)
print("-- inner_1 end --")
return ret
print('-- wrapper_out1 end --')
return inner1
def wrapper_out2(func):
print('-- wrapper_out_2 start --')
def inner2(*args, **kwargs):
print("-- inner_2 start --")
print("-- inner_2 end --")
print('-- wrapper_out_2 end --')
return inner2
@wrapper_out2
@wrapper_out1
def test():
print("--test--")
return 1 * 2
if __name__ == '__main__':
print(">>>>>>>>>>>>>>")
print(test())
執行結果
-- wrapper_out_1 start --
-- wrapper_out1 end --
-- wrapper_out_2 start --
-- wrapper_out_2 end --
>>>>>>>>>>>>>>
-- inner_2 start --
-- inner_1 start --
--test--
-- inner_1 end --
-- inner_2 end --
2
解析
裝飾器的預加載順序是從上往下, 先將裝飾器函數寫入內存
裝飾器的執行順序是以最靠近函數體的裝飾器開始執行(從內到外)
類裝飾器
源碼示例
class WrapperOut(object):
def __init__(self, func):
print('start init ~~~~~`')
print('func name is %s ' % func.__name__)
self.__func = func
print('end init ~~~~~`')
def __call__(self, *args, **kwargs):
print('start test')
self.__func()
print('end test')
@WrapperOut
def test():
print('this is test func')
if __name__ == '__main__':
print(">>>>>>>>>>>")
test()
執行結果
start init ~~~~~`
func name is test?
end init ~~~~~`
>>>>>>>>>>>
start test
this is test func
end test
解析
類裝飾器是利用了類初始化 init 析構方法來處理 被裝飾函數的傳入
以及使用 call 方法來滿足被裝飾函數的執行觸發
原文鏈接:https://www.cnblogs.com/shijieli/p/16185776.html
相關推薦
- 2022-06-06 CSS3動畫:wifi 焦點擴散漸變
- 2022-06-30 PyTorch詳解經典網絡ResNet實現流程_python
- 2022-04-04 微信小程序:獲取用戶手機號碼的過程
- 2022-09-09 Python?cv.Canny()方法參數與使用方法_python
- 2022-08-14 Shell腳本實現監測文件變化的示例詳解_linux shell
- 2022-08-01 Flutter移動端進行多渠道打包發布的全過程_Android
- 2023-11-23 python獲取文件夾內所有文件并改名
- 2022-10-24 解析Golang中引用類型是否進行引用傳遞_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支