Python 中的装饰器如何工作?
应用装饰器:要将装饰器应用于某个函数,可以使用 @decorator_name 语法糖,放在函数定义之前。这相当于在函数定义后立即调用装饰器并将函数作为参数传递给它。
执行流程:当调用被装饰的函数时,实际上是在调用装饰器返回的新函数。这意味着您可以在实际执行目标函数之前或之后插入自定义行为。
示例:基本装饰器
def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapperdef say_hello():print("Hello!")say_hello()# 输出:# Something is happening before the function is called.# Hello!# Something is happening after the function is called.
在这个例子中,my_decorator 是一个简单的装饰器,它包装了 say_hello 函数,在调用前后打印消息。
带参数的装饰器
def repeat(num_times):def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):result = func(*args, **kwargs)return resultreturn wrapperreturn decorator_repeatdef greet(name):print(f"Hello {name}")greet("Alice")# 输出:# Hello Alice# Hello Alice# Hello Alice
这里,repeat 是一个装饰器工厂,它根据提供的 num_times 参数生成一个具体的装饰器。
类装饰器
def add_method(cls):def decorator(func):setattr(cls, func.__name__, func)return clsreturn decoratorclass MyClass:passdef new_method(self):print("This is a dynamically added method.")obj = MyClass()obj.new_method() # 输出: This is a dynamically added method.
在这个例子中,add_method 是一个类装饰器,它向 MyClass 动态添加了一个新的方法。
@classmethod 和 @staticmethod:用于定义类方法和静态方法。
@property:用于将类的方法转换为只读属性。
@functools.lru_cache:用于缓存函数的结果以提高性能。
@dataclasses.dataclass:用于自动为类生成特殊方法(如 __init__() 和 __repr__())。
示例:使用 @property
class Circle:def __init__(self, radius):self._radius = radiusdef radius(self):"""The radius property."""print("Getting radius")return self._radiusdef radius(self, value):if value >= 0:self._radius = valueelse:raise ValueError("Radius must be non-negative")circle = Circle(5)print(circle.radius) # 输出: Getting radius\n5circle.radius = 10print(circle.radius) # 输出: Getting radius\n10
使用多个装饰器
def decorator_one(func):def wrapper():print("Decorator one")func()return wrapperdef decorator_two(func):def wrapper():print("Decorator two")func()return wrapperdef hello():print("Hello!")hello()# 输出:# Decorator one# Decorator two# Hello!
在这个例子中,decorator_two 首先被应用,然后是 decorator_one。
THE END






