Decorators 是強大的工具,允許我們修改函數或 Class 的行為。 Decorators 可以某種方式修改 Class。這通常涉及返回一個新 Class,該新 Class 用一些修改或增強的功能替換原始 Class。
PYTHON
defadd_attribute(cls): cls.new_attribute ="New attribute added by decorator"return cls@add_attributeclassMyClass():pass# Areate an instance of MyClassobj =MyClass()# Access the new attributeprint(obj.new_attribute)# Output: New attribute added by decorator
下面是一範例,它將任何調用的方法的結果乘以 10。 在這種情況下,double_results decorator 會檢查 Class 的所有方法,如果找到任一個可調用方法,它將用 double_decorator 函數包裝它,使結果值加倍。
PYTHON
defdouble_results(cls):# iterate over all attributesfor attr_name, attr_value in cls.__dict__.items():ifcallable(attr_value):# if the attribute is a methodsetattr(cls, attr_name, double_decorator(attr_value))return clsdefdouble_decorator(func):defwrapper(*args,**kwargs):returnfunc(*args, **kwargs)*10return wrapper@double_resultsclassMyClass:defadd(self,a,b):return a + b# create an instance of MyClassobj =MyClass()# call the 'add' methodprint(obj.add(2, 2))# Output: 40
Class decorators 是一個更高層次的概念,不僅需要了解 Classes 如何工作,還需要了解 decorators 如何工作。
classCallCount:def__init__(self,f): self.f = f self.count =0def__call__(self,*args,**kwargs): self.count +=1print(f"This function is called {self.count} times")return self.f(*args, **kwargs)@CallCountdefhello(name):print(f"Hello, {name}")
執行結果:
This function is called 1 times
Hello, Python
Decorator class 用於計時函數執行:
PYTHON
import timeclassTimer:def__init__(self,func): self.func = funcdef__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@Timerdefcomplex_calculation(n):returnsum(i*i for i inrange(n))print(complex_calculation(10000))
執行結果:
Executing complex_calculation took 0.001001 s
333283335000
範例 – 帶參數的 Decorator Class
要創建帶有參數的 Class-based decorator,我們需要確保 Class 本身接受這些參數。
classDecoratorClass:def__init__(self,value): self.value = valuedef__call__(self,func):defwrapper(*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 resultreturn wrapperdefincrement(self): self.value +=1decorator =DecoratorClass(10)decorator.increment()@decoratordeftest_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 語法的限制,允許任何有效的表達式充當裝飾器;允許更具表現力和更複雜的裝飾器。