Python 裝飾器:為您的函數賦予超能力

你好,有抱負的 Python 程式設計師!今天,我們將深入 Python 裝飾器的神奇世界。將裝飾器想成為可以增強你的函數超能力的魔法包裝紙。很刺激對吧?讓我們一起踏上這次旅程!

Python - Decorators

裝飾器是什麼?

想像一下你有一個美麗包裝的禮物。包裝紙並不會改變禮物的內容,但它讓禮物看起來更漂亮,對吧?這正是 Python 中裝飾器對你的函數所做的。它們包圍你的函數,添加額外的功能,而不改變原始函數本身。

讓我們從一個簡單的例子開始:

def my_decorator(func):
def wrapper():
print("在函數被調用之前有事情發生。")
func()
print("在函數被調用之後有事情發生。")
return wrapper

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

say_hello()

如果你運行這段代碼,你會看到:

在函數被調用之前有事情發生。
Hello!
在函數被調用之後有事情發生。

讓我們來解析一下:

  1. 我們定義了一個裝飾器函數 my_decorator,它接受一個函數作為參數。
  2. my_decorator 內部,我們定義了一個 wrapper 函數,它在調用原始函數之前和之後添加一些行為。
  3. 我們使用 @my_decorator 語法將我們的裝飾器應用於 say_hello 函數。
  4. 當我們調用 say_hello() 時,它實際上是在調用包裝後的函數版本。

這不是很好嗎?我們剛剛為我們的 say_hello 函數添加了一些額外的行為,而沒有修改其代碼!

帶參數的裝飾器

但是等等,還有更多!如果我们的函數需要參數呢?沒問題!我們可以修改我們的裝飾器來處理這個:

def my_decorator(func):
def wrapper(*args, **kwargs):
print("在函數被調用之前。")
result = func(*args, **kwargs)
print("在函數被調用之後。")
return result
return wrapper

@my_decorator
def add(a, b):
return a + b

print(add(3, 5))

這將輸出:

在函數被調用之前。
在函數被調用之後。
8

在這裡,*args**kwargs 讓我們的裝飾器可以處理任意數量的位置和關鍵字參數。

內置裝飾器

Python 提供了一些內置的裝飾器,它們非常有用。讓我們來探索它們!

@classmethod 裝飾器

@classmethod 裝飾器用於定義對類本身進行操作的方法,而不是類的實例。

class Pizza:
def __init__(self, ingredients):
self.ingredients = ingredients

@classmethod
def margherita(cls):
return cls(['mozzarella', 'tomatoes'])

@classmethod
def prosciutto(cls):
return cls(['mozzarella', 'tomatoes', 'ham'])

print(Pizza.margherita().ingredients)
print(Pizza.prosciutto().ingredients)

這將輸出:

['mozzarella', 'tomatoes']
['mozzarella', 'tomatoes', 'ham']

在這裡,margheritaprosciutto 是類方法,它們用預定義的配料創建並返回新的 Pizza 實例。

@staticmethod 裝飾器

靜態方法是那些不對實例或類進行操作的方法。它們只是碰巧住在類中的普通函數。

class Math:
@staticmethod
def add(a, b):
return a + b

print(Math.add(5, 10))

這將輸出:

15

@property 裝飾器

@property 裝飾器允許你定義可以像屬性一樣訪問的方法。

class Circle:
def __init__(self, radius):
self._radius = radius

@property
def radius(self):
return self._radius

@property
def area(self):
return 3.14 * self._radius ** 2

c = Circle(5)
print(c.radius)
print(c.area)

這將輸出:

5
78.5

在這裡,我們可以像訪問屬性一樣訪問 radiusarea,但它們實際上是方法。

@functools.wraps 裝飾器

這個裝飾器用於在創建裝飾器時保留原始函數的元數據。

from functools import wraps

def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""這是包裝函數"""
return func(*args, **kwargs)
return wrapper

@my_decorator
def my_function():
"""這是我的函數"""
pass

print(my_function.__name__)
print(my_function.__doc__)

這將輸出:

my_function
這是我的函數

如果没有 @wraps,函數名和文檔字符串將是包裝函數的。

總結

裝飾器是 Python 中的一個強大功能,它允許你修改或增強函數和方法。它們在框架和庫中被廣泛使用,用於添加如日誌記錄、訪問控制等 功能。

記住,掌握裝飾器的關鍵是實踐。嘗試創建自己的裝飾器並將它們應用於不同的函數。很快,你就會像專業人士一樣將你的函數包裹在超能力之中!

以下是本章涵蓋的裝飾器的總結表:

裝飾器 目的
@classmethod 定義對類本身進行操作的方法
@staticmethod 定義不對實例或類進行操作的方法
@property 定義可以像屬性一樣訪問的方法
@functools.wraps 在創建裝飾器時保留原始函數的元數據

開心編程,願你的函數永遠都被美麗地裝飾!

Credits: Image by storyset