1. 引言
装饰器是 Python 中一个非常强大的工具,它允许我们以一种优雅的方式扩展和修改函数或方法的行为。通过装饰器,我们可以在不修改原始代码的情况下为函数添加额外的功能。本文将详细介绍 Python 中的函数装饰器,包括其定义、使用方式、应用场景,并通过一个综合详细的例子展示如何使用装饰器。
2. 装饰器的基本概念
装饰器本质上是一个返回函数的函数。它接受一个函数作为参数,并返回一个增强后的函数。在 Python 中,装饰器通常通过 @ 符号来使用。装饰器可以用来修改函数的行为,而不需要改变函数的代码。
2.1. 装饰器的定义和使用
一个简单的装饰器的定义如下:
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 是一个装饰器,它接受函数 say_hello 作为参数,并返回一个新的函数 wrapper。当调用 say_hello 时,实际上调用的是 wrapper 函数。
2.2 带参数的装饰器
装饰器不仅可以装饰无参数的函数,还可以装饰带参数的函数。我们需要在内部函数 wrapper 中添加相应的参数,并在调用被装饰函数时传递这些参数。例如:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice")
运行上述代码,输出结果为:
Something is happening before the function is called.
Hello, Alice!
Something is happening after the function is called.
2.3 带参数的装饰器函数
有时,我们希望装饰器本身能够接受参数。要实现这一点,我们可以定义一个返回装饰器的函数。例如:
def my_decorator_with_args(text):
def my_decorator(func):
def wrapper(*args, **kwargs):
print(f"{text} before the function is called.")
result = func(*args, **kwargs)
print(f"{text} after the function is called.")
return result
return wrapper
return my_decorator
@my_decorator_with_args("Custom message")
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice")
运行上述代码,输出结果为:
Custom message before the function is called.
Hello, Alice!
Custom message after the function is called.
在这个例子中,my_decorator_with_args 是一个接受参数的装饰器函数,它返回一个实际的装饰器 my_decorator。
3. 常见的装饰器应用场景
装饰器在实际开发中有很多应用场景,下面是几个常见的例子:
3.1 日志记录
装饰器可以用来记录函数的调用日志,包括函数的输入参数和返回值。例如:
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with arguments {args} and {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 arguments (2, 3) and {}
add returned 5
3.2 访问控制
装饰器可以用来控制函数的访问权限,例如检查用户是否具有调用函数的权限。
def require_permission(permission):
def decorator(func):
def wrapper(*args, **kwargs):
if not has_permission(permission):
print(f"Permission denied: {permission}")
return None
return func(*args, **kwargs)
return wrapper
return decorator
def has_permission(permission):
# 假设有一个实际的权限检查逻辑
return permission == "admin"
@require_permission("admin")
def delete_user(user_id):
print(f"User {user_id} deleted")
delete_user(123) # 有权限时执行函数
运行上述代码,输出结果为:
User 123 deleted
3.3 缓存
装饰器可以用来缓存函数的返回结果,以提高性能。例如:
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(35))
使用缓存装饰器后,计算斐波那契数列的速度将显著提高。
4. 综合示例
我们将通过一个综合示例来展示如何使用装饰器。这个示例将包含一个日志记录装饰器、一个权限检查装饰器和一个缓存装饰器。示例代码如下:
import time
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with arguments {args} and {kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper
def require_permission(permission):
def decorator(func):
def wrapper(*args, **kwargs):
if not has_permission(permission):
print(f"Permission denied: {permission}")
return None
return func(*args, **kwargs)
return wrapper
return decorator
def has_permission(permission):
return permission == "admin"
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@log
@require_permission("admin")
@cache
def expensive_computation(x):
time.sleep(2) # 模拟耗时计算
return x * x
# 测试综合示例
print(expensive_computation(3))
print(expensive_computation(3)) # 第二次调用时应使用缓存
运行上述代码,输出结果为:
Calling expensive_computation with arguments (3,) and {}
expensive_computation returned 9
9
Calling expensive_computation with arguments (3,) and {}
expensive_computation returned 9
9
解释
- 日志记录装饰器:记录函数的调用,包括输入参数和返回值。
- 权限检查装饰器:检查用户是否具有调用函数的权限。
- 缓存装饰器:缓存函数的返回结果,以提高性能。
通过这种方式,我们可以在不修改函数本身的情况下,为函数添加额外的功能。
5. 总结
装饰器是 Python 中一个非常强大的工具,可以用来扩展和修改函数或方法的行为。通过装饰器,我们可以在不修改原始代码的情况下为函数添加额外的功能。在实际开发中,装饰器有很多应用场景,包括日志记录、访问控制、性能优化等。希望本文能够帮助你更好地理解和使用 Python 中的装饰器。