
Class Decorators
Decorators 是強大的工具,允許我們修改函數或 Class 的行為。 Decorators 可以某種方式修改 Class。這通常涉及返回一個新 Class,該新 Class 用一些修改或增強的功能替換原始 Class。
def add_attribute(cls):
cls.new_attribute = "New attribute added by decorator"
return cls
@add_attribute
class MyClass():
pass
# Areate an instance of MyClass
obj = MyClass()
# Access the new attribute
print(obj.new_attribute) # Output: New attribute added by decorator
下面是一範例,它將任何調用的方法的結果乘以 10。 在這種情況下,double_results
decorator 會檢查 Class 的所有方法,如果找到任一個可調用方法,它將用 double_decorator
函數包裝它,使結果值加倍。
def double_results(cls):
# iterate over all attributes
for attr_name, attr_value in cls.__dict__.items():
if callable(attr_value): # if the attribute is a method
setattr(cls, attr_name, double_decorator(attr_value))
return cls
def double_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs) * 10
return wrapper
@double_results
class MyClass:
def add(self, a, b):
return a + b
# create an instance of MyClass
obj = MyClass()
# call the 'add' method
print(obj.add(2, 2)) # Output: 40
當您有需要應用於多個 Class 的修改時,使用 Class decorators 是最有意義的。 如果修改特定的單個 Class,則直接修改該 Class 可能會更簡單、更清晰。
Decorator Class
Python 中的 decorator 是用於修改函數、方法或 Class 的任何可調用物件。 可調用物件是任何可以被調用的物件 (具有 __call__
方法的函數或 Class)。
使用 Class 實現的 decorator 可以提供更多的靈活性和對裝飾應用方式的控制。
簡單的 decorator 來追蹤函數被調用的次數:
class CallCount:
def __init__(self, f):
self.f = f
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"This function is called {self.count} times")
return self.f(*args, **kwargs)
@CallCount
def hello(name):
print(f"Hello, {name}")
執行結果:
This function is called 1 times
Hello, Python
Decorator class 用於計時函數執行:
import time
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start_time = time.time()
result = self.func(*args, **kwargs)
end_time = time.time()
print(f"Executing {self.func.__name__} took {end_time - start_time:4f} s")
return result
@Timer
def complex_calculation(n):
return sum(i*i for i in range(n))
print(complex_calculation(10000))
執行結果:
Executing complex_calculation took 0.001001 s
333283335000
範例 – 帶參數的 Decorator Class
要創建帶有參數的 Class-based decorator,我們需要確保 Class 本身接受這些參數。
class Repeat:
def __init__(self, num_times):
self.num_times = num_times
def __call__(self, func):
def wrapper(*args, **kwargs):
for _ in range(self.num_times):
result = func(*args, **kwargs)
return result
return wrapper
@Repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("Alice")
執行結果:
Hello Alice
Hello Alice
Hello Alice
範例 – Decorator Class 實例
class DecoratorClass:
def __init__(self, value):
self.value = value
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f"Before function call, value is: {self.value}")
result = func(*args, **kwargs)
print(f"After function call, value is: {self.value}")
return result
return wrapper
def increment(self):
self.value += 1
decorator = DecoratorClass(10)
decorator.increment()
@decorator
def test_function():
print("Inside the function")
test_function()
執行結果:
Hello Alice
Hello Alice
Hello Alice
PEP 614
PEP 代表 Python Enhancement Proposal (增強提案),它是一個描述 Python 新功能和改進的標準。 這些 PEP 在被接受並在 Python 中實現之前,經過了仔細的審查和討論過程。
PEP 614 (Python 3.9 ver.) 消除了 decorators 語法的限制,允許任何有效的表達式充當裝飾器;允許更具表現力和更複雜的裝飾器。
參考資料
decorator — Python 3.11.4 documentation
PEP 318 – Decorators for Functions and Methods | peps.python.org
PEP 3129 – 類裝飾器 | peps.python.org
PEP 614 – 放寬對裝飾器的語法限制 | peps.python.org
PEP 698 – 覆蓋靜態類型裝飾器 | peps.python.org
Python進階技巧 (3) — 神奇又美好的 Decorator ,嗷嗚! | by Jack Cheng | 整個程式都是我的咖啡館 | Medium
Python語法糖系列_上帝De助手的博客-CSDN博客_語法糖
詳解Python修飾器(語法糖)_咆哮的阿傑的博客-CSDN博客_修飾器
python中裝飾器&語法糖(syntax sugar)@_Mr_ggx的博客-CSDN博客_python怎樣達到和語法糖同樣的效果
Python 中帶參數的裝飾器 - GeeksforGeeks
collections - 如何在 python 中使用 kwargs 作為裝飾器的參數_python_酷徒編程知識庫
Python 中帶參數的裝飾器 - GeeksforGeeks
DAY09-搞懂Python的裝飾器 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
Last updated
Was this helpful?