Python装饰器:为函数添加额外的功能,如计时、日志等。
Python装饰器是一种功能强大的机制,可以在不修改原始函数代码的情况下向函数添加额外的功能或修改其行为。装饰器本质上是一个函数,接受目标函数作为参数,并返回修改后的目标函数或额外的功能。
在Python中,函数是一等公民,这意味着它们可以像任何其他变量一样被传递给其他函数。由于装饰器本质上是一个接收函数并返回函数的函数,因此可以将两者结合起来使用,从而达到许多有用的效果。
使用Python装饰器的目的是提高代码的可读性、复用性和可维护性。常见的用途包括日志记录、性能分析、输入验证、缓存、认证授权等。
一个很好的装饰器例子是计时器。假设我们有一个函数来计算斐波那契数列中特定索引的值:
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
为了测量这个函数的性能,我们可以添加一个计时器装饰器:
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__} took {(end - start):.6f}s to run.')
return result
return wrapper
@timer
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
在这个例子中,我们定义了一个装饰器函数timer,它接收一个函数作为参数func。装饰器函数返回一个包装函数wrapper,它用于将原始函数func包装起来,并添加计时器逻辑。包装函数接收任意数量的位置参数和关键字参数,并记录函数执行的起始和结束时间。在函数执行完成后,它打印出函数名称和执行时间,并返回原始结果。
使用装饰器可以轻松地将这个计时器逻辑添加到任何其他函数中:
@timer
def some_function(*args, **kwargs):
# 函数代码
另一个常见的用例是日志记录装饰器。假设我们有一个函数,接收一些参数并执行一些操作:
def some_function(arg1, arg2):
# 函数代码
为了调试或监控此函数的行为,我们可以添加一个日志功能,记录函数调用和返回值:
def logger(func):
def wrapper(*args, **kwargs):
print(f'[INFO] calling {func.__name__} with args {args}, {kwargs}')
result = func(*args, **kwargs)
print(f'[INFO] {func.__name__} returned {result}')
return result
return wrapper
@logger
def some_function(arg1, arg2):
# 函数代码
在这个例子中,我们定义了一个装饰器函数logger,它接收一个函数作为参数func。装饰器函数返回一个包装函数wrapper,它用于将原始函数func包装起来,并添加日志逻辑。包装函数接收任意数量的位置参数和关键字参数,并打印调用信息。在函数执行完成后,它还打印返回值,并返回原始结果。
使用装饰器可以轻松地将这个日志逻辑添加到任何其他函数中:
@logger
def some_function(*args, **kwargs):
# 函数代码
Python装饰器还可以组合使用,从而实现更复杂的功能。例如,我们可以使用两个装饰器来实现一个既记录日志又测量性能的函数:
@logger
@timer
def some_function(*args, **kwargs):
# 函数代码
在这个例子中,我们将日志记录装饰器和计时器装饰器组合在一起,并应用于some_function函数。装饰器的顺序非常重要,因为它们按照从下到上的顺序应用。在此示例中,计时器装饰器将首先应用,并将包装函数传递给日志记录装饰器,它将进一步包装包装函数。
小结:
Python装饰器是一种强大的机制,可以为函数添加额外的功能或修改其行为。常见的用途包括日志记录、性能分析、输入验证、缓存、认证授权等。装饰器本质上是一个接收函数并返回函数的函数,可以将多个装饰器组合使用以实现复杂的功能。使用Python装饰器可以提高代码的可读性、复用性和可维护性。
