XiWind 西風之劍
HomeTechProContactGitHub
  • About
  • Git
    • Windows Terminal、PowerShell 安裝
    • Git 開始使用
    • Branch 入門
    • 合併多個 Commit , 編輯
    • 額外功能
  • deep learning
    • Dilated Convolution
  • Python
    • GIL 【全域直譯器鎖】
    • PyPy 【JIT 編譯器】
    • Decorator 【修飾器】
      • Class Decorators
  • Python library
    • abc 【抽象 Class】
      • ABC, ABCMeta
      • __abstractmethods__, get_cache_token, update_abstractmethods
    • dataclasses 【數據 Class】
      • make_dataclass(), replace(), is_dataclass(), __post_init__
    • enum 【列舉 Class】
      • Flag, auto(), unique, verify()
      • 範例
    • concurrent.futures 【執行緒、程序】
      • Future, Module Functions
    • queue 【佇列、同步】
      • full(), empty(), qsize(), join(), task_done()
    • functools 【可調用物件】
      • ordering、wrapper、partial
      • Overloading
    • heapq 【堆積佇列】
      • heapify(), merge(), nlargest(), nsmallest()
    • time 【時間】
      • time(), monotonic(), perf_counter()...
      • sleep(), 範例...
    • logging 【日誌】
Powered by GitBook
On this page
  • Class Decorators
  • Decorator Class
  • 範例 – 帶參數的 Decorator Class
  • 範例 – Decorator Class 實例
  • PEP 614
  • 參考資料

Was this helpful?

  1. Python
  2. Decorator 【修飾器】

Class Decorators


Decorators 是強大的工具,允許我們修改函數或 Class 的行為。 Decorators 可以某種方式修改 Class。這通常涉及返回一個新 Class,該新 Class 用一些修改或增強的功能替換原始 Class。

PYTHON
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 函數包裝它,使結果值加倍。

PYTHON
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 decorators 是一個更高層次的概念,不僅需要了解 Classes 如何工作,還需要了解 decorators 如何工作。

當您有需要應用於多個 Class 的修改時,使用 Class decorators 是最有意義的。 如果修改特定的單個 Class,則直接修改該 Class 可能會更簡單、更清晰。

Decorator Class


Python 中的 decorator 是用於修改函數、方法或 Class 的任何可調用物件。 可調用物件是任何可以被調用的物件 (具有 __call__ 方法的函數或 Class)。

使用 Class 實現的 decorator 可以提供更多的靈活性和對裝飾應用方式的控制。

簡單的 decorator 來追蹤函數被調用的次數:

PYTHON
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 用於計時函數執行:

PYTHON
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 本身接受這些參數。

PYTHON
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 實例


PYTHON
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 語法的限制,允許任何有效的表達式充當裝飾器;允許更具表現力和更複雜的裝飾器。

參考資料


PreviousDecorator 【修飾器】Nextabc 【抽象 Class】

Last updated 1 year ago

Was this helpful?

Decorators允許輕鬆修改類和函數,而無需更改其原始碼。 這遵循物件導向編程中的 。(物件應該對擴展開放,但對修改應該關閉)

Open–closed principle
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教學] 裝飾詞原理到應用 | Max行銷誌
Python Decorator 入門教學
Python 有哪些好玩的語法糖? - 知乎
Python語法糖系列_上帝De助手的博客-CSDN博客_語法糖
詳解Python修飾器(語法糖)_咆哮的阿傑的博客-CSDN博客_修飾器
Python 中甜甜的語法糖 - 騰訊雲開發者社區-騰訊雲
Python 中甜甜的語法糖_牛客博客
python中裝飾器&語法糖(syntax sugar)@_Mr_ggx的博客-CSDN博客_python怎樣達到和語法糖同樣的效果
Python 函數裝飾器 | 菜鳥教程
裝飾器 - 廖雪峰的官方網站
Python 中的裝飾器 - GeeksforGeeks
Python 中帶參數的裝飾器 - GeeksforGeeks
collections - 如何在 python 中使用 kwargs 作為裝飾器的參數_python_酷徒編程知識庫
Python 中帶參數的裝飾器 - GeeksforGeeks
DAY09-搞懂Python的裝飾器 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
collections - 如何在 python 中使用 kwargs 作為裝飾器的參數_python_酷徒編程知識庫
Python 中帶參數的裝飾器 - GeeksforGeeks
Page cover image