Python装饰器实现方法及应用场景详解
1. 概述
装饰器是 Python 中非常重要的概念,几乎所有 Python 框架都大量使用到了装饰器。它可以用于功能增强、日志处理、输入验证和安全控制等场景。
装饰器本质上是一个 Python 函数或类,并在不改变原函数/方法定义的基础上对其进行增强。Python 中借助函数式编程的特点,可以很方便地实现装饰器。
2. Python装饰器实现方法
装饰器可以使用函数或类实现,下面分别介绍。
2.1 函数实现装饰器
函数装饰器包装器的通用格式如下所示:
def decorator(func):
def wrapper(*args, **kwargs):
# 在调用原函数前进行增强操作
res = func(*args, **kwargs)
# 在调用原函数后进行增强操作
return res
return wrapper
将被装饰的函数作为参数传给装饰器函数,返回一个新的经过增强的函数并替换掉原函数。
在 wrapper
函数中,可以在调用原函数前后进行额外的逻辑处理。
例如,下面的代码实现了一个简单的计算程序,加入了装饰器对输入的检查功能,如果输入值为负数则自动转换成正数:
def check_input(func):
def wrapper(*args, **kwargs):
for arg in args:
if arg < 0:
print(f"Warning: Invalid input value ({arg}), automatically converts it to positive value.")
arg = -arg
return func(*args, **kwargs)
return wrapper
@check_input
def add(x, y):
return x + y
print(add(1, -2)) # 输出:Warning: Invalid input value (-2), automatically converts it to positive value.
# -1
在上面的代码中,add
函数被 check_input
装饰器装饰,该装饰器会检查传入参数的值是否为负数,若是则转化为相应正数,然后才调用 add
函数,返回结果。
2.2 类实现装饰器
类装饰器的实现方式类似于函数装饰器。一个类装饰器通常具有 __call__
方法,且能够接受被装饰的方法或函数作为参数,并在其上执行增强操作。
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
# 在调用原函数前进行增强操作
res = self.func(*args, **kwargs)
# 在调用原函数后进行增强操作
return res
实现后,我们可以使用装饰器类对函数进行装饰。
例如,下面的代码实现了一个简单的装饰器类,该装饰器类在调用被装饰的函数前后打印一行信息:
class Logger:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(f"Call {self.func.__name__} function...")
res = self.func(*args, **kwargs)
print(f"{self.func.__name__} function finished.")
return res
@Logger
def foo(x, y):
return x + y
print(foo(1, 2)) # 输出:Call foo function...
# foo function finished.
# 3
在上面的代码中,foo
函数被 Logger
装饰器装饰,该装饰器会在调用 foo
函数前后打印一行信息,然后才调用 foo
函数,返回结果。
3. 装饰器应用场景
3.1 功能增强
装饰器可以对函数进行增强。例如,在框架中处理请求/响应对象时,可以使用装饰器简化代码复杂度。
例如,下面的代码实现了一个装饰器类,对 Flask 框架中的请求进行记录:
def record_request(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"Request URL: {request.url}")
print(f"Request IP Address: {request.remote_addr}")
print(f"Request Method: {request.method}")
print(f"Request Time: {end - start:.3f}s")
return res
return wrapper
@app.route("/")
@record_request
def hello():
return "Hello World!"
在上面的代码中,record_request
装饰器类会在调用 hello
函数前后记录请求 URL、IP地址、请求方法和请求时间。
Flask 能够接收来自浏览器或其他客户端的HTTP请求,它内置了多个数据结构来处理请求,其中重要的一点就是当前请求的信息都在一个名为request的全局变量里,可以通过 Flask 的request模块来使用。
3.2 输入验证
装饰器可以对函数的输入参数类型进行检查。例如,在 Web 开发中需要对输入内容进行验证,以保证数据的有效性和安全性。
例如,下面的代码实现了一个装饰器函数,对输入的数值范围进行检查。
def check_range(min_val, max_val):
def decorator(func):
def wrapper(*args, **kwargs):
for arg in args:
if arg < min_val or arg > max_val:
raise ValueError(f"Invalid value for parameter ({arg}), should between ({min_val}, {max_val}).")
return func(*args, **kwargs)
return wrapper
return decorator
@check_range(min_val=0, max_val=100)
def square(x):
return x * x
print(square(3))
print(square(-1)) # 抛出异常:ValueError: Invalid value for parameter (-1), should between (0, 100).
在上面的代码中,check_range
装饰器函数会检查函数输入的参数值是否在指定的范围内,如果不在所指定的范围内,则抛出异常(ValueError
),提示用户输入有误。
3.3 输出记录
装饰器可以对函数的输出结果进行记录。例如,记录函数的返回结果,方便后续分析和调试。
下面是一个简单示例程序,演示对函数输出记录的实现:
def log_result(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
print(f"Function {func.__name__} returned: {res}")
return res
return wrapper
@log_result
def add(x, y):
return x + y
add(1, 2) # 输出:Function add returned: 3
在上面的程序中, add
函数被 log_result
装饰器装饰,该装饰器会在调用完 add
函数后,记录函数的返回结果。
4. 总结
装饰器是 Python 中应用广泛的编程语法,在函数功能扩展、输入输出检查、日志记录等场景中都有广泛应用。只要掌握装饰器的实现方式和应用场景,就能有效提升 Python 中程序开发的效率和质量。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python装饰器实现方法及应用场景详解 - Python技术站