《從零開始的Python筆記》Day#8:Python魔法糖-裝飾器(上)

更新 發佈閱讀 11 分鐘
raw-image

Python系列的筆記到這邊就差不多要告個段落,我介紹了基礎語法與進階語法的功能與使用方式。基礎語法對於初學者來說是滿容易理解而且能快速上手的部分,進階語法則是初學者的噩夢,常常讓人難以理解也不知道怎麼使用,不過它卻是讓大家提升程式設計能力的好工具。 一開始大家不需要去死記硬背這些進階語法,只需要大概有個印象即可,以後在開發時就可能突然想到有個適合現在情境或任務的進階技巧可以使用。


✨ 裝飾器 (Decorators)

裝飾器在Python中是一種很特別的存在,學習它的時候很難理解,使用的時候卻很方便,尤其是在大型專案上常常可以在程式中看到它的存在。 當你想讓原本函式新增其他功能,又不想更動原本函式時,裝飾器就是一種強大而靈活的工具,只是對於初學者來說真的非常抽象難以理解。因此只希望大家可以先知道什麼是裝飾器以及它可以做到哪些事情,未來在開發過程中有機會可以用上。

由於它允許開發者在 不改變函數定義 的情況下,動態地增加或修改函數的行為,因此裝飾器讓程式的結構更加靈活且模組化,非常適合用於擴展函數功能,例如日誌記錄、驗證、計時等。

💡簡單來說,我們可以把裝飾器理解為一種函數專用的外掛!

基本概念: 語法糖(@)

  • 裝飾器是一個函數,接受一個函數作為參數,並返回一個新的函數。
  • 使用 @decorator_name 語法糖(syntactic sugar)應用裝飾器。

為什麼需要裝飾器?

  • 增加函數的功能:在不修改原始函數代碼的前提下,動態在外層添加新的行為。
  • 程式碼重用:可將常見的功能(如日誌記錄、權限檢查、計時等)封裝成裝飾器,讓多個函數共享邏輯。
  • 程式碼清晰與分層:裝飾器使業務邏輯與輔助功能(如錯誤處理等)分離,提高程式可讀性。

基本特性:函數作為參數與回傳值

裝飾器的核心基於 Python 的函數是一等公民(First-Class Functions),表示函數可以:

  • 作為參數傳遞
  • 作為回傳值返回

手動模擬裝飾器功能

# 定義函數作為參數
def greet(func):
def wrapper():
print("Before calling the function...")
func() # 呼叫傳入的函數
print("After calling the function...")
return wrapper

def say_hello():
print("Hello!")

# 使用裝飾器
decorated = greet(say_hello)
decorated()

# 輸出
Before calling the function...
Hello!
After calling the function...

建立簡單裝飾器

def my_decorator(func):
def wrapper():
print("執行裝飾器的邏輯(開始)")
func() # 執行被裝飾的函數
print("執行裝飾器的邏輯(結束)")
return wrapper

@my_decorator
def my_function():
print("執行原始函數的邏輯")

my_function()

# 輸出
執行裝飾器的邏輯(開始)
執行原始函數的邏輯
執行裝飾器的邏輯(結束)

裝飾帶參數的函數

def my_decorator(func):
def wrapper(*args, **kwargs): # 接收任意參數
print("開始執行裝飾器")
result = func(*args, **kwargs) # 執行原始函數
print("結束執行裝飾器")
return result
return wrapper

@my_decorator
def add_numbers(a, b):
print(f"總和為:{a + b}")
return a + b

result = add_numbers(5, 10)
print(f"回傳結果:{result}")

# 輸出
開始執行裝飾器
總和為:15
結束執行裝飾器
回傳結果:15

支援裝飾器接受參數

  • 當需要讓裝飾器本身可配置時,可使用多一層嵌套的函數
def repeat(times):  # 接收參數的裝飾器
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator

@repeat(3) # 重複執行 3 次
def say_hello(name):
print(f"Hello, {name}!")

say_hello("Alice")

# 輸出
Hello, Alice!
Hello, Alice!
Hello, Alice!

類裝飾器

  • 除了函數形式的裝飾器,也可以使用類作為裝飾器
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0

def __call__(self, *args, **kwargs):
self.count += 1
print(f"函數 {self.func.__name__} 已被調用 {self.count} 次")
return self.func(*args, **kwargs)

@CountCalls
def say_hello():
print("Hello!")

say_hello()
say_hello()

# 輸出
函數 say_hello 已被調用 1
Hello!
函數 say_hello 已被調用 2
Hello!

嵌套多個裝飾器

  • 當使用多個裝飾器時,它們的執行順序是從下到上(內到外)
  • 相當於:decorator1(decorator2(say_hello))
def decorator1(func):
def wrapper(*args, **kwargs):
print("執行 decorator1")
return func(*args, **kwargs)
return wrapper

def decorator2(func):
def wrapper(*args, **kwargs):
print("執行 decorator2")
return func(*args, **kwargs)
return wrapper

@decorator1
@decorator2
def say_hello():
print("Hello, World!")

say_hello()

# 輸出
執行 decorator1
執行 decorator2
Hello, World!

保留函數meta data

  • 裝飾器會導致函數的原始資訊丟失,我們可以使用 functools.wraps 來解決這個問題

丟失meta data

def my_decorator(func):
def wrapper(*args, **kwargs):
print("開始執行裝飾器")
result = func(*args, **kwargs)
print("結束執行裝飾器")
return result
return wrapper

@my_decorator
def add_numbers(a, b):
"""計算兩個數字的和"""
return a + b

print(add_numbers.__name__) # 輸出: wrapper
print(add_numbers.__doc__) # 輸出: None

保留meta data

from functools import wraps

def my_decorator(func):
@wraps(func) # 保留原函數的元數據
def wrapper(*args, **kwargs):
print("開始執行裝飾器")
result = func(*args, **kwargs)
print("結束執行裝飾器")
return result
return wrapper

@my_decorator
def add_numbers(a, b):
"""計算兩個數字的和"""
return a + b

print(add_numbers.__name__) # 輸出: add_numbers
print(add_numbers.__doc__) # 輸出: 計算兩個數字的和

優點

裝飾器充分發揮了 Python 函數作為一等公民的優勢,允許在現有代碼的基礎上靈活擴展功能。通過裝飾器的應用,我們可以改善程式結構、優化開發效率,並提升函數的靈活性與可用性。

raw-image

適用情境

裝飾器作為一種外掛存在,可以在各種既有的函數上新增額外的功能,因此使用範圍非常廣泛。

raw-image


留言
avatar-img
留言分享你的想法!
avatar-img
Ethan的AI學習筆記
4會員
28內容數
我是一個不務正業的資料科學家,從零開始學習的路途上跌跌撞撞,跌過許多坑,也撞過許多牆... 當有人迷失方向時,希望這些筆記可以成為你的指南針。
Ethan的AI學習筆記的其他內容
2025/08/23
這篇筆記主要是介紹資料科學家的好朋友:迭代器和生成器! 迭代器與生成器是大家在處理資料以及訓練模型時常常會使用到的工具,請務必熟悉他們的用法!!!
Thumbnail
2025/08/23
這篇筆記主要是介紹資料科學家的好朋友:迭代器和生成器! 迭代器與生成器是大家在處理資料以及訓練模型時常常會使用到的工具,請務必熟悉他們的用法!!!
Thumbnail
2025/08/16
大部分在學習程式語言的人很常會看到或是聽到一個很抽象的詞:物件導向 對於初學者來說,又出現了一個很難以理解的名詞,而且在學習上的確也是很常讓人碰壁的一部分。雖然有著不小的學習障礙,但是對於提升程式設計能力有很大的幫助,因此建議大家可以多點耐心去接觸並且練習如何使用它。
Thumbnail
2025/08/16
大部分在學習程式語言的人很常會看到或是聽到一個很抽象的詞:物件導向 對於初學者來說,又出現了一個很難以理解的名詞,而且在學習上的確也是很常讓人碰壁的一部分。雖然有著不小的學習障礙,但是對於提升程式設計能力有很大的幫助,因此建議大家可以多點耐心去接觸並且練習如何使用它。
Thumbnail
2025/08/14
學習到這個階段,大家如果都有跟上的話已經可以試著自行開發一些工具或是演算法了。不過Python還有提供許多進階的功能可以幫助我們在開發的過程中更順暢、更有效率。 ⚠️ 例外處理 (Exception)
Thumbnail
2025/08/14
學習到這個階段,大家如果都有跟上的話已經可以試著自行開發一些工具或是演算法了。不過Python還有提供許多進階的功能可以幫助我們在開發的過程中更順暢、更有效率。 ⚠️ 例外處理 (Exception)
Thumbnail
看更多
你可能也想看
Thumbnail
Python資料視覺化在數據分析中扮演關鍵角色,透過視覺化捕捉數據模式、趨勢和異常,透過Matplotlib等工具創建專業圖表變相對簡單和高效。
Thumbnail
Python資料視覺化在數據分析中扮演關鍵角色,透過視覺化捕捉數據模式、趨勢和異常,透過Matplotlib等工具創建專業圖表變相對簡單和高效。
Thumbnail
什麼是Python python是電腦程式語言的一種,如同python官方網站上的介紹 "Python是一種程式語,可讓你更快速地工作並更有效的整合系統"。簡單地說,就是你可用python這個程式語言去告訴電腦你想要作什麼,讓電腦來幫你完成你要作的事情。
Thumbnail
什麼是Python python是電腦程式語言的一種,如同python官方網站上的介紹 "Python是一種程式語,可讓你更快速地工作並更有效的整合系統"。簡單地說,就是你可用python這個程式語言去告訴電腦你想要作什麼,讓電腦來幫你完成你要作的事情。
Thumbnail
Python的模組和庫是可重用的程式碼塊,可透過import語句引入。特定部分可以透過from和import引入,並可使用as指定別名。第三方模組可透過pip工具安裝並在程式碼中使用。此外,也可以創建自定義模組並在其他Python文件中引用。
Thumbnail
Python的模組和庫是可重用的程式碼塊,可透過import語句引入。特定部分可以透過from和import引入,並可使用as指定別名。第三方模組可透過pip工具安裝並在程式碼中使用。此外,也可以創建自定義模組並在其他Python文件中引用。
Thumbnail
本文介紹了各種運算符的用法和優先級,包括算術運算符、比較運算符、賦值運算符、邏輯運算符、位元運算符、成員運算符和身份運算符。每種運算符都有詳細的描述和示例程式碼,幫助理解其功能和用法。
Thumbnail
本文介紹了各種運算符的用法和優先級,包括算術運算符、比較運算符、賦值運算符、邏輯運算符、位元運算符、成員運算符和身份運算符。每種運算符都有詳細的描述和示例程式碼,幫助理解其功能和用法。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
Python是一種易學且功能強大的程式語言,具有直譯、動態語法等特性,並擁有豐富的標準庫。它在各領域如Web開發、數據科學和人工智慧等得到廣泛應用,並被許多大公司如Google和Facebook等使用。Python還有強大的框架、豐富的交互機能、和龐大的社區。
Thumbnail
Python是一種易學且功能強大的程式語言,具有直譯、動態語法等特性,並擁有豐富的標準庫。它在各領域如Web開發、數據科學和人工智慧等得到廣泛應用,並被許多大公司如Google和Facebook等使用。Python還有強大的框架、豐富的交互機能、和龐大的社區。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News