了解Python中的装饰器函数吗?如何实现?
装饰器是Python语言中一种非常有用的特性,它可以用来修改或者扩展一个函数的功能,而无需修改函数的源代码。装饰器本质上是一个函数,接受一个函数作为参数,并返回一个新的函数。
为了更好地理解装饰器的概念,首先我们来看一个简单的例子。假设我们有一个函数add,功能是将两个数相加并返回结果:
def add(a, b):
return a + b
现在,我们想给这个函数添加一个打印日志的功能,即在函数执行之前打印函数名和参数,执行之后打印函数名和返回结果。我们可以通过在函数内部添加打印语句来实现这个功能,但这会修改函数的源代码。使用装饰器,我们可以在不修改函数源代码的情况下实现这个功能,如下所示:
def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling function {func.__name__} with arguments {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} returned {result}")
return result
return wrapper
上面的代码定义了一个装饰器函数logger,它接受一个函数作为参数,并返回一个新的函数wrapper。wrapper函数用来包装原始的函数,实现添加日志的功能。在wrapper函数中,我们首先打印函数名和参数,然后调用原始函数,并将返回结果保存到result变量中,最后再打印函数名和返回结果。最后,我们返回wrapper函数作为装饰器的结果。
现在,我们可以使用装饰器来装饰add函数,使其具有添加日志的功能:
@logger
def add(a, b):
return a + b
通过在函数定义之前加上@logger,我们将add函数传递给logger函数进行装饰。装饰器实际上等同于以下代码:
add = logger(add)
现在调用add函数的时候,会自动附带上日志功能:
>>> add(2, 3)
Calling function add with arguments (2, 3), {}
Function add returned 5
5
上述例子实现了一个简单的装饰器函数,但实际中装饰器函数可以更加复杂,并可以实现更多的功能。装饰器可以用来缓存函数的结果、检查函数参数的合法性、记录函数执行时间等。下面,我们来看几个常见的装饰器用法。
1. 缓存装饰器
缓存装饰器可以用来缓存函数的结果,以避免重复计算。下面是一个简单的缓存装饰器:
def cache(func):
results = {}
def wrapper(*args, **kwargs):
key = (*args, frozenset(kwargs.items()))
if key not in results:
results[key] = func(*args, **kwargs)
return results[key]
return wrapper
上述代码中,results是一个字典,用来保存已经计算过的函数结果。在wrapper函数中,我们首先根据参数生成一个 的key,然后判断这个key是否在results字典中。如果在,直接返回对应的结果;如果不在,调用原始函数计算结果,并保存到results字典中。最后,返回计算结果。
使用装饰器来装饰函数,即可实现缓存的功能:
@cache
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
2. 计时装饰器
计时装饰器可以用来记录函数的执行时间。下面是一个简单的计时装饰器:
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time} seconds to execute")
return result
return wrapper
上述代码中,我们使用time模块来获取当前时间。在wrapper函数中,我们记录下函数执行前的时间start_time,执行完函数后的时间end_time,然后计算两者之差,得到函数的执行时间。最后,打印出函数名和执行时间。
使用装饰器来装饰函数,即可实现计时的功能:
@timer
def heavy_computation():
# some heavy computation
在调用heavy_computation函数时,装饰器会自动记录函数的执行时间并打印出来。
以上是关于装饰器函数的一些基本介绍和示例用法。装饰器是Python中非常有用的特性,它可以让我们在不修改函数源代码的情况下,动态地修改或者扩展函数的功能。掌握装饰器的使用,可以让我们的代码更加简洁、灵活和可复用。
