網站首頁 編程語言 正文
前言
1.裝飾器本質是一個語法糖,是對被裝飾方法或類進行的功能擴充,是一種面向切面的實現方法
2.裝飾器可以分成方法裝飾器和類裝飾器,他們的區別是一個是用函數實現的裝飾器,一個是用類實現的裝飾器,他們也都能在方法和類上進行裝飾
3.類裝飾器看起來結構更加清晰,因此下面的代碼實現的裝飾器全是類裝飾器
一、創建方式
1.創建“裝飾方法”的類裝飾器
from functools import wraps
# 裝飾器類
class MyDecorator(object):
def __init__(self, plusNum):
self.plusNum = plusNum # 裝飾器入參
def __call__(self, func):
@wraps(func) # @wraps保證裝飾器不改變被裝飾方法的原有函數結構
def wrapped_function(*args, **kwargs):
# 調用被裝飾方法前執行一些操作 ---------------
# 如果不加@wraps,此處打印結果將是
funcName = func.__name__
print("funcName: {}".format(funcName))
# ---------------------------------------
# 修改被裝飾方法的入參 --
num1 = args[0] + 2
num2 = args[1] + 3
args = (num1, num2)
# -------------------
# 執行被裝飾方法 -------------
res = func(*args, **kwargs)
# -------------------------
# 調用被裝飾方法后執行一些操作 -------------
print("do something after the func...")
# -------------------------------------
# 修改被裝飾方法的出參 --
res += self.plusNum
# -------------------
# 返回被裝飾方法的參數
return res
# 返回裝飾器方法
return wrapped_function
# 被裝飾的方法
@MyDecorator(3)
def add(num1, num2):
return num1+num2
if __name__ == '__main__':
# 整體執行流程:
# 1. 打印 add 方法名
# 2. 修改被裝飾方法入參
# 3. 執行被裝飾方法
# 4. 調用被裝飾方法后執行一些操作
# 5. 修改被裝飾方法的出參
# 6. 打印結果
print(add(5, 3))
# funcName: add
# do something after the func...
# 16
2.創建“裝飾類中方法”的類裝飾器
from functools import wraps
# 裝飾器類
class MyDecorator(object):
def __init__(self, plusNum):
self.plusNum = plusNum # 裝飾器入參
def __call__(self, func):
@wraps(func) # @wraps保證裝飾器不改變被裝飾方法的原有函數結構
def wrapped_function(*args, **kwargs):
# 此處與直接裝飾方法相同
# 調用被裝飾方法前執行一些操作 ---------------
# 如果不加@wraps,此處打印結果將是
funcName = func.__name__
print("funcName: {}".format(funcName))
# ---------------------------------------
# 此處需要注意,如果需要修改入參的值,那么傳參的索引是從1開始而不是從0開始,因為第一個入參的值是實例本身self
# 修改被裝飾方法的入參 --
num1 = args[1] + 2
num2 = args[2] + 3
args = (args[0], num1, num2)
# -------------------
# 此處與直接裝飾方法相同
# 執行被裝飾方法 -------------
res = func(*args, **kwargs)
# -------------------------
# 此處與直接裝飾方法相同
# 調用被裝飾方法后執行一些操作 -------------
print("do something after the func...")
# -------------------------------------
# 此處與直接裝飾方法相同
# 修改被裝飾方法的出參 --
res += self.plusNum
# -------------------
# 返回被裝飾方法的參數
return res
# 返回裝飾器方法
return wrapped_function
class Operation(object):
# 被裝飾的類方法
@MyDecorator(3)
def add(self, num1, num2):
return num1+num2
if __name__ == '__main__':
op = Operation()
print(op.add(3, 5))
# funcName: add
# do something after the func...
# 16
3.創建“裝飾類”的類裝飾器
from functools import wraps
# 裝飾器類
class MyDecorator(object):
def __init__(self, plusNum):
self.plusNum = plusNum # 裝飾器入參
def __call__(self, Cls):
@wraps(Cls) # @wraps保證裝飾器不改變被裝飾類的原有結構
def wrapped_function(*args, **kwargs):
# 調用被裝飾類前執行一些操作 ---------------
# 如果不加@wraps,此處打印結果將是
clsName = Cls.__name__
print("clsName: {}".format(clsName))
# ---------------------------------------
# 修改被裝飾類的入參 ---
num1 = args[0] + 2
num2 = args[1] + 3
args = (num1, num2)
# -------------------
# 初始化被裝飾類 -------------
cls = Cls(*args, **kwargs)
# -------------------------
# 初始化后執行一些操作 --------------------
print("do something after the func...")
# -------------------------------------
# 給類實例增加增加屬性和方法 ---------------------
cls.mul = 3 # 增加屬性
cls.plusNumber = self.plusNumber # 增加方法
# -------------------------------------------
# 返回實例
return cls
# 返回裝飾器方法
return wrapped_function
def plusNumber(self, num):
return num + self.plusNum
# 被裝飾的類
@MyDecorator(3)
class Operation(object):
def __init__(self, num1, num2):
self.num1 = num1
self.num2 = num2
def add(self):
num3 = self.num1 + self.num2
num4 = self.plusNumber(num3*self.mul) # 使用裝飾器插入的屬性和方法
return num4
if __name__ == '__main__':
# 整體執行流程:
# 1. 打印 Operation 類名
# 2. 修改類的初始化參數
# 3. 初始化類
# 4. 初始化完成后執行一些方法
# 5. 給初始化的實例新增 mul 屬性和 plusNumber 方法
# 6. 實例執行 add 函數并調用新增的裝飾函數和裝飾屬性
# 7. 輸出結果
op = Operation(3, 5)
print(op.add())
# clsName: Operation
# do something after the func...
# 42
二、常用場景
1.記錄日志
# todo
2.性能測試
# todo
3.循環執行
# todo
4.攔截器
# todo
5.數據預處理(數據清洗)
# todo
6.功能植入
# todo
原文鏈接:https://blog.csdn.net/weixin_43721000/article/details/125590006
相關推薦
- 2022-07-11 Jenkins修改端口號, jenkins容器修改默認端口號
- 2022-10-07 Docker容器操作方法詳解_docker
- 2022-06-12 Python取讀csv文件做dbscan分析_python
- 2023-03-20 一文詳解pygame.sprite的精靈碰撞_python
- 2022-07-23 C++強制類型轉換的四種方式_C 語言
- 2022-07-21 react中的redux
- 2022-08-04 Django框架之路由用法_python
- 2022-02-27 Error in render: “TypeError: Cannot read propertie
- 最近更新
-
- 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同步修改后的遠程分支