装饰器(Decorator)是 Python 中的一种高级特性,它用于在不修改函数或类的源代码的情况下,动态地增加或修改它们的功能。装饰器本质上是一个返回函数的函数,它可以在函数调用之前或之后执行额外的代码。
装饰器的语法使用 @
符号,放在函数定义的前一行。让我们详细讲解装饰器,并通过一些示例来理解它的工作原理。
基本装饰器
装饰器是一个接受函数作为参数并返回一个新函数的高阶函数。以下是一个简单的装饰器示例:
1 2 3 4 5 6 7 8 9 10 11 12 |
def simple_decorator(func): def wrapper(): print("Something is happening before the function is called.") func() print("Something is happening after the function is called.") return wrapper @simple_decorator def say_hello(): print("Hello!") say_hello() |
输出:
1 2 3 |
Something is happening before the function is called. Hello! Something is happening after the function is called. |
在这个示例中:
simple_decorator
是一个装饰器函数,它接受一个函数func
作为参数,并返回一个新的wrapper
函数。wrapper
函数在调用func
之前和之后添加了额外的代码。@simple_decorator
语法将say_hello
函数包裹在simple_decorator
中,使得say_hello
被调用时实际上执行的是wrapper
函数。
带参数的装饰器
如果被装饰的函数接受参数,装饰器也需要处理这些参数。以下是一个带参数的装饰器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def decorator_with_args(func): def wrapper(*args, **kwargs): print("Before the function call") result = func(*args, **kwargs) print("After the function call") return result return wrapper @decorator_with_args def greet(name): print(f"Hello, {name}!") greet("Alice") |
输出:
1 2 3 |
Before the function call Hello, Alice! After the function call |
在这个示例中,wrapper
函数使用 *args
和 **kwargs
来接受任意数量的位置参数和关键字参数,并将它们传递给原始函数 func
。
带参数的装饰器工厂
有时候,我们希望装饰器本身能够接受参数。为此,我们可以编写一个返回装饰器的函数,这种函数称为装饰器工厂。以下是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def repeat(num_times): def decorator_repeat(func): def wrapper(*args, **kwargs): for _ in range(num_times): func(*args, **kwargs) return wrapper return decorator_repeat @repeat(3) def say_hello(): print("Hello!") say_hello() |
输出:
1 2 3 |
Hello! Hello! Hello! |
在这个示例中:
repeat
是一个装饰器工厂,它接受参数num_times
并返回一个decorator_repeat
装饰器。decorator_repeat
装饰器将num_times
传递给wrapper
函数,以控制原始函数func
被调用的次数。
装饰类方法
装饰器也可以用于类方法。以下是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def method_decorator(func): def wrapper(self, *args, **kwargs): print(f"Calling method {func.__name__}") return func(self, *args, **kwargs) return wrapper class MyClass: @method_decorator def say_hello(self, name): print(f"Hello, {name}!") obj = MyClass() obj.say_hello("Alice") |
输出:
1 2 |
Calling method say_hello Hello, Alice! |
在这个示例中,装饰器 method_decorator
用于类方法 say_hello
,并在调用方法之前打印一条消息。
内置装饰器
Python 提供了一些常用的内置装饰器,例如 @staticmethod
、@classmethod
和 @property
。
@staticmethod
:将方法转换为静态方法,不需要实例参数self
。@classmethod
:将方法转换为类方法,接受类参数cls
。@property
:将方法转换为属性,使得可以像访问属性一样访问方法。
以下是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Example: def __init__(self, value): self._value = value @staticmethod def static_method(): print("This is a static method.") @classmethod def class_method(cls): print(f"This is a class method of {cls.__name__}.") @property def value(self): return self._value @value.setter def value(self, new_value): if new_value < 0: raise ValueError("Value cannot be negative.") self._value = new_value obj = Example(10) obj.static_method() # 输出: This is a static method. obj.class_method() # 输出: This is a class method of Example. print(obj.value) # 输出: 10 obj.value = 20 print(obj.value) # 输出: 20 |
通过这些示例,我们可以看到装饰器在 Python 中的强大功能,它使得代码更加简洁、可读,并且易于维护。