Python中的装饰器
1. 什么是装饰器
在Python中,装饰器(Decorator)是一种用来修改函数或方法的行为的高级技术。装饰器本质上是一个包装函数,它接受一个函数作为输入,并返回一个新的函数作为输出。
装饰器可以在函数执行前后执行一些额外的逻辑,或者在函数执行时进行一些额外的操作,而不需要修改函数本身的定义。这样可以实现一些横切关注点的逻辑(cross-cutting concerns),比如日志记录、性能测试、权限校验等。
2. 装饰器的基本语法
在Python中,装饰器通常是一个函数,以@
符号紧跟着函数名的方式使用,将装饰器函数应用到目标函数上。下面是一个简单的装饰器示例:
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 wrapper
@my_decorator
def 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
是一个简单的装饰器函数,它接受一个函数作为参数,并在目标函数执行前后打印额外的信息。@my_decorator
语法糖将装饰器应用到say_hello
函数上,并在调用say_hello
函数时执行装饰器的逻辑。
3. 装饰器的应用场景
3.1 记录日志
装饰器可以用来记录函数的调用信息,比如函数名称、参数、返回值等,方便后续跟踪调试。下面是一个记录日志的装饰器示例:
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned: {result}")
return result
return wrapper
@log
def add(a, b):
return a + b
add(2, 3)
运行结果:
Calling add with args: (2, 3), kwargs: {}
add returned: 5
3.2 缓存结果
装饰器还可以用来实现结果的缓存,避免重复计算相同输入的结果。下面是一个简单的缓存装饰器示例:
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
print(f"Returning cached result for {args}")
return cached_results[args]
else:
result = func(*args)
cached_results[args] = result
print(f"Caching result {result} for {args}")
return result
return wrapper
@cache
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
print(factorial(5))
print(factorial(4))
print(factorial(5))
运行结果:
Caching result 1 for (0,)
Caching result 2 for (1,)
Caching result 6 for (2,)
Caching result 24 for (3,)
Caching result 120 for (4,)
Returning cached result for (5,)
120
Returning cached result for (4,)
24
Returning cached result for (5,)
120
4. 复合装饰器
可以通过多个装饰器组合在一起,对同一个函数进行多个装饰操作。当使用多个装饰器时,装饰器执行的顺序与装饰器在函数上的声明顺序相反。
def uppercase(func):
def wrapper():
original_result = func()
modified_result = original_result.upper()
return modified_result
return wrapper
def exclamation(func):
def wrapper():
original_result = func()
modified_result = original_result + "!"
return modified_result
return wrapper
@exclamation
@uppercase
def say_hello():
return "hello"
print(say_hello())
运行结果:
HELLO!
在上述示例中,say_hello
函数被先应用 uppercase
装饰器,再应用 exclamation
装饰器,因此最终函数返回的结果是将 “hello” 转换为大写并添加感叹号的 “HELLO!”。
5. 实际应用
装饰器是Python中非常强大和灵活的特性,可以优雅地解决代码中的一些共性问题,提高代码的可读性和可维护性。除了上述的应用场景外,装饰器还可以用来实现权限验证、性能测试、异常处理等功能。在编写复杂的Python应用程序时,合理地使用装饰器可以让代码更加清晰和简洁。