Decorators Pattern in Python

Decorators Pattern in Python

装饰器模式(Decorator Pattern)是一种设计模式,它允许你通过将对象放入包装对象中来为原对象添加新的行为。装饰器模式是一种替代继承的技术,它通过一种无需子类化增加功能的方式来扩展类的功能。

使用 decorators,可以在不直接修改源码的情况下修改 function 或 method 的功能,从而让代码更简洁,更 Pythonic

The fundamentals

functions in python

python 中函数是 first-class object,可以赋值给变量、作为参数传递、作为返回值、在运行时动态创建和修改,结合内置的装饰器,可以方便地实现横切关注点,无需额外的 AOP 库。

First-Class Object

  • being expressible as an anonymous literal value
  • being storable in variables
  • being storable in data structures
  • having an intrinsic identity (independent of any given name)
  • being comparable for equality with other entities
  • being passable as a parameter to a procedure/function
  • being returnable as the result of a procedure/function
  • being constructible at runtime
  • being printable
  • being readable
  • being transmissible among distributed processes
  • being storable outside running processes

如下是使用 Python 中函数特性的例子:

PYTHON
# 1. Assigning Functions to Variablessay_hello = greetprint(say_hello("Alice"))  # Output: Hello, Alice!# 2. Pass function as an argumentdef apply_function(func, value):    return func(value)def uppercase(text):    return text.upper()result = apply_function(uppercase, "hello")print(result)  # Output: HELLO# 3. Return function from another function (Nested Function)def make_multiplier(n):    def multiplier(x):        return x * n    return multiplierdouble = make_multiplier(2)print(double(5))  # Output: 10

Simple Demo

结合以上特性,可以实现一个简单的装饰器,实现计时功能

Tips: 建议使用 functools.wraps 保留原函数的元信息,如__name__、__doc__

PYTHON
from functools import wrapsfrom time import timedef simple_decorator(func):    @wraps(func)   # 此注解用于保留func的元信息    def wrapper(*args, **kwargs):        print(f"function <{func.__name__}> is called")        start_time = time()        result = func(*args, **kwargs)        print(f"Function execution time: {time() - start_time}")        return result    return wrapper@simple_decoratordef calculate():    sum = 0    for i in range(1000000):        sum += i    print(sum)# 上述代码等价于# @simple_decorator syntax 等价于 calculate = simple_decorator(calculate)calculate()[OUTPUT]function <calculate> is called499999500000Function execution time: 0.16027212142944336

Chaining Decorators

Python 允许使用多个装饰器,可以通过 @decorator1 @decorator2@decoratorN 的方式来实现

PYTHON
from functools import wrapsdef star(func):    @wraps(func)    def wrapper(*args, **kwargs):        print("*" * 30)        func(*args, **kwargs)        print("*" * 30)    return wrapperdef hyphen(func):    @wraps(func)    def wrapper(*args, **kwargs):        print("-" * 30)        func(*args, **kwargs)        print("-" * 30)    return wrapper@star@hyphendef greet(name):    print(f"Hello, {name}!")greet("Python")[OUTPUT]******************************------------------------------Hello, Python!------------------------------******************************

Best Practices(?)

  • Parameter Validation Decorators
  • Method Routing
  • Caching and Memoization

@lru_cache

PYTHON
from functools import lru_cache@lru_cache(maxsize=128)def fibonacci(n):    if n < 2:        return n    else:        return fibonacci(n-1) + fibonacci(n-2)

getter/setter

PYTHON
class Person:    def __init__(self, name, age):        self._name = name        self._age = age    @property    def name(self):        return self._name    @name.setter    def name(self, value):        self._name = value    @property    def age(self):        return self._age    @age.setter    def age(self, value):        self._age = valueperson = Person("Alice", 25)print(person.name)  # Output: Aliceperson.name = "Bob"print(person.name)  # Output: Bob

Ref

What are “first-class” objects? —— StackOverFlow

Decorators Pattern in Python

https://vluv.space/decorators_pattern/

作者

GnixAij

发布于

2024-12-03

更新于

2025-08-12

许可协议

评论