> For the complete documentation index, see [llms.txt](https://docs.xiwind-corp.com/tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xiwind-corp.com/tech/python/decorator-xiu-shi-qi/class-decorators.md).

# Class Decorators

## Class Decorators

***

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

{% code title="PYTHON" %}

```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
```

{% endcode %}

下面是一範例，它將任何調用的方法的結果乘以 10。 在這種情況下，`double_results` decorator 會檢查 Class 的所有方法，如果找到任一個可調用方法，它將用 `double_decorator` 函數包裝它，使結果值加倍。

{% code title="PYTHON" %}

```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
```

{% endcode %}

{% hint style="info" %}
**Class decorators 是一個更高層次的概念，不僅需要了解 Classes 如何工作，還需要了解 decorators 如何工作。**
{% endhint %}

{% hint style="info" %}
**Decorators允許輕鬆修改類和函數，而無需更改其原始碼。 這遵循物件導向編程中的** [**Open–closed principle**](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle) **。(物件應該對擴展開放，但對修改應該關閉)**
{% endhint %}

{% hint style="success" %}
**當您有需要應用於多個 Class 的修改時，使用 Class decorators 是最有意義的。 如果修改特定的單個 Class，則直接修改該 Class 可能會更簡單、更清晰。**
{% endhint %}

## Decorator Class

***

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

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

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

{% code title="PYTHON" %}

```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}")

```

{% endcode %}

**執行結果:**

```txt
This function is called 1 times
Hello, Python
```

**Decorator class 用於計時函數執行：**

{% code title="PYTHON" %}

```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))
```

{% endcode %}

**執行結果:**

```txt
Executing complex_calculation took 0.001001 s
333283335000
```

### 範例 – 帶參數的 Decorator Class

***

要創建帶有參數的 Class-based decorator，我們需要確保 Class 本身接受這些參數。

{% code title="PYTHON" %}

```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")
```

{% endcode %}

**執行結果:**

```txt
Hello Alice
Hello Alice
Hello Alice
```

### 範例 – Decorator Class 實例

***

{% code title="PYTHON" %}

```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()
```

{% endcode %}

**執行結果:**

```txt
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](https://docs.python.org/3/glossary.html#term-decorator)

[PEP 318 – Decorators for Functions and Methods | peps.python.org](https://peps.python.org/pep-0318/)

[PEP 3129 – 類裝飾器 | peps.python.org](https://peps.python.org/pep-3129/)

[PEP 614 – 放寬對裝飾器的語法限制 | peps.python.org](https://peps.python.org/pep-0614/)

[PEP 698 – 覆蓋靜態類型裝飾器 | peps.python.org](https://peps.python.org/pep-0698/)

[Python進階技巧 (3) — 神奇又美好的 Decorator ，嗷嗚！ | by Jack Cheng | 整個程式都是我的咖啡館 | Medium](https://medium.com/citycoddee/python%E9%80%B2%E9%9A%8E%E6%8A%80%E5%B7%A7-3-%E7%A5%9E%E5%A5%87%E5%8F%88%E7%BE%8E%E5%A5%BD%E7%9A%84-decorator-%E5%97%B7%E5%97%9A-6559edc87bc0)

[\[Python教學\] 裝飾詞原理到應用 | Max行銷誌](https://www.maxlist.xyz/2019/12/07/python-decorator/)

[Python Decorator 入門教學](https://blog.techbridge.cc/2018/06/15/python-decorator-%E5%85%A5%E9%96%80%E6%95%99%E5%AD%B8/)

[Python 有哪些好玩的語法糖？ - 知乎](https://www.zhihu.com/question/57470958)

[Python語法糖系列\_上帝De助手的博客-CSDN博客\_語法糖](https://blog.csdn.net/five3/article/details/83474633)

[詳解Python修飾器(語法糖)\_咆哮的阿傑的博客-CSDN博客\_修飾器](https://blog.csdn.net/qq_34914551/article/details/107358768)

[Python 中甜甜的語法糖 - 騰訊雲開發者社區-騰訊雲](https://cloud.tencent.com/developer/article/1671829)

[Python 中甜甜的語法糖\_牛客博客](https://blog.nowcoder.net/n/a8d75227c51f42609375281d7205abd4)

[python中裝飾器&語法糖(syntax sugar)@\_Mr\_ggx的博客-CSDN博客\_python怎樣達到和語法糖同樣的效果](https://blog.csdn.net/guanguoxiang/article/details/46500813)

[Python 函數裝飾器 | 菜鳥教程](https://www.runoob.com/w3cnote/python-func-decorators.html)

[裝飾器 - 廖雪峰的官方網站](https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584)

[Python 中的裝飾器 - GeeksforGeeks](https://www.geeksforgeeks.org/decorators-in-python/)

[Python 中帶參數的裝飾器 - GeeksforGeeks](https://www.geeksforgeeks.org/decorators-with-parameters-in-python/)

[collections - 如何在 python 中使用 kwargs 作為裝飾器的參數\_python\_酷徒編程知識庫](https://stackoverflow.com/questions/70043312/how-to-use-kwargs-as-parameter-for-decorator-in-python)

[Python 中帶參數的裝飾器 - GeeksforGeeks](https://www.geeksforgeeks.org/decorators-with-parameters-in-python/)

[DAY09-搞懂Python的裝飾器 - iT 邦幫忙::一起幫忙解決難題，拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10200763)

[collections - 如何在 python 中使用 kwargs 作為裝飾器的參數\_python\_酷徒編程知識庫](https://stackoverflow.com/questions/70043312/how-to-use-kwargs-as-parameter-for-decorator-in-python)

[Python 中帶參數的裝飾器 - GeeksforGeeks](https://www.geeksforgeeks.org/decorators-with-parameters-in-python/)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xiwind-corp.com/tech/python/decorator-xiu-shi-qi/class-decorators.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
