what is a decorator ?

Today I want to talk about decorators

In Python, a ​decorator is a powerful and flexible design pattern that allows you to ​modify or extend the behavior of a function, method, or class without permanently altering its source code. Decorators leverage ​first-class functions and ​closures to wrap or "decorate" the target object, enabling reusable and clean code.


Core Concepts

  1. Decorators Are Functions
    A decorator is a higher-order function that:

    • Accepts a function/method/class as input.
    • Returns a new function (or class) that enhances or replaces the original.

    Example: Simple decorator to log function execution:

    def logger_decorator(func):
        def wrapper(*args, ​**kwargs):
            print(f"Calling {func.__name__}...")
            result = func(*args, ​**kwargs)  # Execute the original function
            print(f"{func.__name__} finished.")
            return result
        return wrapper
    
    @logger_decorator
    def greet(name):
        print(f"Hello, {name}!")
    
    greet("Alice")  
    # Output:
    # Calling greet...
    # Hello, Alice!
    # greet finished.
  2. The @ Syntax Sugar
    The @decorator syntax simplifies applying decorators. It is equivalent to:

    def greet(name): ...
    greet = logger_decorator(greet)
  3. Preserving Metadata with functools.wraps
    Decorators replace the original function's metadata (e.g., __name____doc__). Use functools.wraps to retain them:

    from functools import wraps
    
    def logger_decorator(func):
        @wraps(func)  # Preserve original metadata
        def wrapper(*args, ​**kwargs):
            ...
        return wrapper

Advanced Use Cases

  1. Decorators with Arguments
    To create a decorator that accepts arguments, use nested functions:

    def repeat(n_times):  # Outer function accepts arguments
        def decorator(func):  # Inner function accepts the target function
            @wraps(func)
            def wrapper(*args, ​**kwargs):
                for _ in range(n_times):
                    result = func(*args, ​**kwargs)
                return result
            return wrapper
        return decorator
    
    @repeat(n_times=3)
    def say_hello():
        print("Hello!")
    
    say_hello()  # Prints "Hello!" three times
  2. Class-Based Decorators
    Classes can act as decorators by implementing the __call__ method:

    class Timer:
        def __init__(self, func):
            self.func = func
    
        def __call__(self, *args, ​**kwargs):
            import time
            start = time.time()
            result = self.func(*args, ​**kwargs)
            print(f"Time: {time.time() - start:.2f}s")
            return result
    
    @Timer
    def slow_function():
        time.sleep(2)
    
    slow_function()  # Output: Time: 2.00s
  3. Decorating Classes
    Decorators can modify classes (e.g., adding methods or properties):

    def add_method(cls):
        def new_method(self):
            return "This is a new method!"
        cls.new_method = new_method
        return cls
    
    @add_method
    class MyClass: ...
    
    obj = MyClass()
    print(obj.new_method())  # Output: This is a new method!

Common Use Cases

  • Logging/Tracing: Track function calls and parameters.
  • Timing: Measure execution time (as shown in Timer example).
  • Authorization/Validation: Check permissions or validate inputs before execution.
  • Caching/Memoization: Cache results (e.g., functools.lru_cache).
  • Retry Logic: Retry a function on failure.
  • Deprecation Warnings: Mark deprecated functions.

Key Notes

  • Order Matters: Multiple decorators are applied bottom-to-top:
    @decorator1
    @decorator2
    def func(): ...
    # Equivalent to: func = decorator1(decorator2(func))
  • Debugging: Use __name__ or tools like inspect to trace decorated functions.
  • Performance: Avoid heavy logic in decorators if performance is critical.

Example: Caching Decorator

from functools import lru_cache

@lru_cache(maxsize=128)  # Built-in decorator for caching
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(50))  # Efficiently computes with memoization

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愚戏师

多谢道友

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值