在Python中,装饰器(Decorator)是一种设计模式,用于修改或增强函数或方法的行为,而无需更改其实际代码。装饰器允许我们以一种灵活且可重用的方式向函数添加新的功能。本文将深入探讨Python装饰器的多种用法,并提供示例代码以帮助理解。
1. 基础装饰器
基础装饰器通过定义一个包装函数来增强另一个函数的功能。下面是一个简单的装饰器示例,它在被装饰函数执行前后打印信息:
def my_decorator(func):
def wrapper():
print("函数调用前发生的事情。")
func()
print("函数调用后发生的事情。")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
2. 带参数的装饰器
有时我们希望装饰器能够接受参数,以提供更灵活的装饰功能。下面是一个接受参数的装饰器示例:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("调用前")
result = func(*args, **kwargs)
print("调用后")
return result
return wrapper
@my_decorator
def greet(name):
print(f"Hello {name}")
greet("Alice")
3. 使用functools.wraps
为了在装饰函数时保留原始函数的元数据(如函数名和文档字符串),我们可以使用functools.wraps
:
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
""“包装函数”""
return func(*args, **kwargs)
return wrapper
@my_decorator
def greet(name):
""“向某人打招呼”"""
print(f"Hello {name}")
print(greet.__name__) # 输出: 'greet'
print(greet.__doc__) # 输出: '向某人打招呼'
4. 类装饰器
装饰器也可以通过类来实现。下面是一个使用类的装饰器示例:
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("调用前")
self.func(*args, **kwargs)
print("调用后")
@MyDecorator
def greet(name):
print(f"Hello {name}")
greet("Alice")
5. 带参数的装饰器
我们可以创建一个接受自己参数的装饰器,如下所示:
def repeat(times):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello")
say_hello()
6. 方法装饰器
装饰器同样可以应用于类的实例方法:
def method_decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
print("方法装饰器")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@method_decorator
def greet(self, name):
print(f"Hello {name}")
obj = MyClass()
obj.greet("Alice")
7. 装饰器栈
可以将多个装饰器应用于同一个函数:
@my_decorator
@repeat(2)
def greet(name):
print(f"Hello {name}")
greet("Alice")
8. 可选参数的装饰器
创建一个可以根据需要带或不带参数的装饰器:
def smart_decorator(arg=None):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if arg:
print(f"参数: {arg}")
return func(*args, **kwargs)
return wrapper
if callable(arg):
return decorator(arg)
return decorator
@smart_decorator
def no_args():
print("无参数")
@smart_decorator("有参数")
def with_args():
print("有参数")
no_args()
with_args()
9. 类方法装饰器
装饰器同样可以应用于类的类方法:
class MyClass:
@classmethod
@my_decorator
def class_method(cls):
print("类方法被调用")
MyClass.class_method()
10. 静态方法装饰器
装饰器也可以应用于类的静态方法:
class MyClass:
@staticmethod
@my_decorator
def static_method():
print("静态方法被调用")
MyClass.static_method()
通过上述示例,我们可以看到装饰器在Python中的多样性和灵活性。它们不仅能够增强函数的功能,还能在不修改原始代码的情况下实现这一点。