Python 裝飾器詳解

裝飾器是 Python 中一種強大的語法特性,它允許在不修改原函數代碼的情況下動態地擴展函數的功能。裝飾器本質上是一個高階函數,它接受一個函數作為參數并返回一個新的函數。

基本裝飾器

1. 簡單裝飾器示例

def my_decorator(func):def wrapper():print("函數執行前")func()print("函數執行后")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()

輸出:

函數執行前
Hello!
函數執行后

2. 裝飾器的工作原理

  • @my_decorator 語法糖等價于 say_hello = my_decorator(say_hello)
  • my_decorator 接收 say_hello 函數作為參數
  • 返回 wrapper 函數,它"包裹"了原函數

帶參數的裝飾器

1. 函數帶參數的裝飾器

def decorator_with_args(func):def wrapper(name):print(f"準備調用 {func.__name__}")func(name)print(f"{func.__name__} 調用完成")return wrapper@decorator_with_args
def greet(name):print(f"Hello, {name}!")greet("Alice")

2. 裝飾器本身帶參數

def repeat(num_times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(num_times):func(*args, **kwargs)return wrapperreturn decorator@repeat(3)
def say_hello(name):print(f"Hello, {name}!")say_hello("Bob")

輸出:

Hello, Bob!
Hello, Bob!
Hello, Bob!

類裝飾器

裝飾器不僅可以是函數,還可以是類:

class CountCalls:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"函數已被調用 {self.num_calls} 次")return self.func(*args, **kwargs)@CountCalls
def example():print("執行示例函數")example()
example()
example()

輸出:

函數已被調用 1 次
執行示例函數
函數已被調用 2 次
執行示例函數
函數已被調用 3 次
執行示例函數

多個裝飾器疊加

可以同時應用多個裝飾器:

def uppercase_decorator(func):def wrapper():result = func()return result.upper()return wrapperdef exclamation_decorator(func):def wrapper():result = func()return result + "!"return wrapper@exclamation_decorator
@uppercase_decorator
def say_hi():return "hi there"print(say_hi())  # 輸出: HI THERE!

注意:裝飾器的應用順序是從下往上,先應用 uppercase_decorator,然后是 exclamation_decorator

內置裝飾器

Python 本身提供了一些內置裝飾器:

  1. @staticmethod - 定義靜態方法
  2. @classmethod - 定義類方法
  3. @property - 將方法轉換為屬性

裝飾器的常見用途

  1. 日志記錄
  2. 性能測試(計算函數執行時間)
  3. 權限驗證
  4. 緩存(備忘錄模式)
  5. 輸入驗證
  6. 注冊插件
  7. 重試機制

性能測試裝飾器示例

import timedef timer(func):def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(f"{func.__name__} 執行時間: {end - start:.4f} 秒")return resultreturn wrapper@timer
def slow_function():time.sleep(2)slow_function()

保留原函數的元信息

使用 functools.wraps 可以保留原函數的元信息:

from functools import wrapsdef my_decorator(func):@wraps(func)def wrapper(*args, **kwargs):"""這是包裝函數的文檔字符串"""print("裝飾器添加的功能")return func(*args, **kwargs)return wrapper@my_decorator
def example():"""這是原函數的文檔字符串"""print("原函數功能")print(example.__name__)  # 輸出: example
print(example.__doc__)   # 輸出: 這是原函數的文檔字符串

總結

裝飾器是 Python 中非常強大的特性,它:

  • 允許在不修改原函數代碼的情況下擴展功能
  • 遵循開放-封閉原則(對擴展開放,對修改封閉)
  • 使代碼更加模塊化和可重用
  • 常用于日志、性能測試、權限控制等場景

掌握裝飾器可以讓你寫出更加優雅和高效的 Python 代碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81563.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81563.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81563.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

無損耗協議:PROFINET和EtherNet IP網關的高效安裝指南

作為風力發電機組監控系統的重要組成部分,PROFINET和EtherNet/IP協議轉換網關倍訊BX-606-EIP的安裝至關重要。作為安裝工,我們要確保網關安裝的高效順利,保證風力發電機組的穩定運行。 首先,我們需要仔細檢查網關的硬件接口,確保所有連接線纜與設備端口相匹配。網關…

Axure元件動作四:設置選中

親愛的小伙伴,在您瀏覽之前,煩請關注一下,在此深表感謝!如有幫助請訂閱專欄! Axure產品經理精品視頻課已登錄CSDN可點擊學習https://edu.csdn.net/course/detail/40420 課程主題:設置選中 主要內容:選中效果全面解析 應用場景:元件、元件組合需要被選中場景 案例展…

大模型為什么學新忘舊(大模型為什么會有災難性遺忘)?

字數:2500字 一、前言:當學霸變成“金魚” 假設你班上有個學霸,數學考滿分,英語拿第一,物理稱霸全校。某天,他突然宣布:“我要全面發展!從今天起學打籃球!” 一周后&am…

通過SMTP協議實現Linux郵件發送配置指南

一、環境準備與基礎配置 1. SMTP服務開通(以qq郵箱為例) 登錄qq郵箱網頁端,進入「設置」-「POP3/SMTP/IMAP」 開啟「SMTP服務」并獲取16位授權碼(替代郵箱密碼使用) 記錄關鍵參數: SMTP服務器地址&#…

react中安裝依賴時的問題 【集合】

目錄 依賴升級/更新 1、 npm install --save-dev 與 npm install 的區別 1. ?安裝位置(依賴類型)? 2. ?package.json 中的區別? 3. ?示例 4. ?何時使用哪種方式? 2、npm install 和 yarn add 有什么不一樣嗎 ?命令語法?: …

Coze 實戰教程 | 10 分鐘打造你的AI 助手

> 文章中的 xxx 自行替換,文章被屏蔽了。 📱 想讓你的xxx具備 AI 對話能力?本篇將手把手教你,如何用 Coze 平臺快速構建一個能與用戶自然交流、自動回復提問的 xxx助手,零代碼、超高效! 📌…

【Spring Cloud Gateway】Nacos整合遇坑記:503 Service Unavailable

一、場景重現 最近在公司進行微服務架構升級,將原有的 Spring Cloud Hoxton 版本升級到最新的 2021.x 版本,同時使用 Nacos 作為服務注冊中心和配置中心。在完成基礎框架搭建后,我使用 Spring Cloud Gateway 作為API 網關,通過 N…

寶塔面板屏蔽垃圾搜索引擎蜘蛛和掃描工具的辦法

首先進入寶塔面板,文件管理進入/www/server/nginx/conf目錄,新建空白文件kill_bot.conf。然后將以下代碼保存到當前文件中。 #禁止垃圾搜索引擎蜘蛛抓取if ($http_user_agent ~* "CheckMarkNetwork|Synapse|Nimbostratus-Bot|Dark|scraper|LMAO|Ha…

Docker拉取鏡像報錯Error response from daemon: Get “https://registry-1.docker.io/v2/“

記一次Docker拉取鏡像的報錯 使用docker拉取鏡像時,出現報錯 [rootcentos8 ~]# sudo docker pull mysql:8.0 Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.T…

Ansible模塊——文件內容修改

修改文件單行內容 ansible.builtin.lineinfile 可以按行修改文件內容,一次修改一行,支持正則表達式。 選項名 類型 默認值 描述 attributesstrnull 設置目標文件的 Linux 文件系統屬性(attribute bits),作用類似于…

如何用PDO實現安全的數據庫操作:避免SQL注入

如何用PDO實現安全的數據庫操作:避免SQL注入 在現代Web應用程序中,數據庫操作是核心功能之一。然而,SQL注入是一種常見的安全漏洞,攻擊者可以通過惡意輸入來操控數據庫,從而獲取敏感信息或破壞數據。使用PHP的PDO&…

使用大語言模型從零構建知識圖譜(中)

從零到一:大語言模型在知識圖譜構建中的實操指南 ©作者|Ninja Geek 來源|神州問學 還沒有看過上篇的讀者可以閱讀《使用大語言模型從零構建知識圖譜(上)》了解整個系列的內容 通過創建一個自定義流程來自動上傳業務數據 在這一節&#…

pycharm連接github(詳細步驟)

【前提:菜鳥學習的記錄過程,如果有不足之處,還請各位大佬大神們指教(感謝)】 1.先安裝git 沒有安裝git的小伙伴,看上一篇安裝git的文章。 安裝git,2.49.0版本-CSDN博客 打開cmd(…

uniapp在APP上如何使用websocket--詳解

UniApp 在 APP 端如何使用 WebSocket以及常見問題 一、WebSocket 基礎概念 WebSocket 是一種在單個TCP連接上進行全雙工通信的協議,適用于實時數據傳輸場景(如聊天室、實時游戲、股票行情等)。 與傳統HTTP對比 特性WebSocketHTTP連接方式…

物聯網賦能7×24H無人值守共享自習室系統設計與實踐!

隨著"全民學習"浪潮的興起,共享自習室市場也欣欣向榮,今天就帶大家了解下在物聯網的加持下,無人共享自習室系統的設計與實際方法。 一、物聯網系統整體架構 1.1 系統分層設計 層級技術組成核心功能用戶端微信小程序/H5預約選座、…

【Linux】ELF與動靜態庫的“暗黑兵法”:程序是如何跑起來的?

目錄 一、什么是庫? 1. C標準庫(libc) 2. C標準庫(libstdc) 二、靜態庫 1. 靜態庫的生成 2. 靜態庫的使用 三、動態庫 1. 動態庫的生成 2. 動態庫的使用 3. 庫運行的搜索路徑。 (1)原因…

滲透測試流程-中篇

#作者:允砸兒 #日期:乙巳青蛇年 四月廿一(2025年5月18日) 今天筆者帶大家繼續學習,網安的知識比較雜且知識面很廣,這一部分會介紹很多需要使用的工具。會用各種工具是做網安的基礎,ok咱們繼續…

[創業之路-358]:從歷史輪回到制度躍遷:中國共產黨創業模式的超越性密碼

人類文明的演進如同一條螺旋上升的階梯,從原始社會的公有制到資本主義私有制的巔峰,再到社會主義對公有制的重構,每一次制度迭代都伴隨著對前序文明的揚棄。中國共產黨自誕生之日起,便以“為人類求解放”為使命,在革命…

NLP基礎

目錄 一、NLP 概述和應用 (一)NLP 的定義與演進歷程 (二)NLP 的多元應用領域 二、文本預處理技術 (一)文本獲取與編碼轉換 (二)文本清洗:去除雜質的精細打磨 &…

【數據結構與算法】ArrayList 與順序表的實現

目錄 一、List 接口 1.1 List 接口的簡單介紹 1.1 常用方法 二、順序表 2.1 線性表的介紹 2.2 順序表的介紹 2.3 順序表的實現 2.3.1 前置條件:自定義異常 2.3.2 順序表的初始化 2.3.2 順序表的實現 三、ArrayList 實現類 3.1 ArrayList 的兩種使用方式 3.2 Array…