Python 函数的装饰器用法
Python 中的函数装饰器是一个经典的特性,它可以让我们在不修改原有函数代码的情况下,添加额外的功能和逻辑。虽然在使用 Python 时,我们可能已经使用了各种装饰器,但是如果我们想系统地了解 Python 函数装饰器,那么就需要更深入地理解它的定义、语法、应用场景等方面。
1. 装饰器的定义
函数装饰器是一个高阶函数,它接受一个函数,并以某种方式返回一个新函数。这个新函数通常会在原函数的基础上添加一些额外的功能,有时还会修改原函数的参数和返回值。
需要注意的是,装饰器并不会修改原函数本身的代码,而是通过类似“包裹”原函数的方式实现增加功能。这种方式称为“封装”,即在函数的前后添加一些额外的代码,实现某种功能(如日志记录、异常处理、缓存等)。
2. 装饰器的语法
Python 函数装饰器的语法非常简单,其基本格式如下:
def decorator(func):
def wrapper(*args, **kwargs):
# 添加装饰器的逻辑
return func(*args, **kwargs)
return wrapper
这个函数用于定义一个装饰器,其中包含一个内部函数 wrapper,用于添加装饰器的逻辑,并在最后返回这个新函数。这个装饰器可以被其他函数调用,在这一过程中,原有的函数就被“包裹”在这个装饰器内部函数中,以实现某种特殊功能。
3. 装饰器的应用场景
Python 函数装饰器的应用场景非常广泛。它可以用于实现函数输出日志,缓存经常使用的计算结果,设置函数超时时间等。
以下是一些比较常见的应用场景:
1)记录函数运行时间:
import time
def run_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__}运行时间: {end_time - start_time}")
return result
return wrapper
@run_time
def test():
time.sleep(3)
test()
2)对函数进行缓存:
CACHE = {}
def cache(func):
def wrapper(*args, **kwargs):
key = str(args) + str(kwargs)
if key in CACHE:
return CACHE[key]
result = func(*args, **kwargs)
CACHE[key] = result
return result
return wrapper
@cache
def calculate(a, b):
return a + b
result = calculate(1, 2)
result = calculate(1, 2) # 第二次调用时已经从缓存中返回结果,不需要再重新计算
3)设置函数超时时间:
import signal
class TimeoutError(Exception):
pass
def timeout(seconds):
def inner(func):
def wrapper(*args, **kwargs):
def signal_handler(signum, frame):
raise TimeoutError("Function call timed out")
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(seconds)
try:
result = func(*args, **kwargs)
signal.alarm(0) # 在函数调用后清除定时器
return result
except:
signal.alarm(0) # 在异常时清除定时器
raise TimeoutError("Function call timed out")
return wrapper
return inner
@timeout(2)
def test():
time.sleep(3)
try:
test()
except TimeoutError:
print("Function call timed out")
4. 装饰器的注意事项
虽然 Python 函数装饰器很方便,但是有几个注意事项需要我们注意:
1)装饰器不能应用于类方法和静态方法
2)装饰器应该被放在函数调用前面
3)多个装饰器,从上到下依次执行
4)装饰器会包装原有函数,因此有可能改变原有函数的属性(如函数名和文档字符串)。
5. 总结
Python 函数装饰器是一种高级技术,它可以在不修改原函数代码的情况下,实现对函数功能的增强。装饰器的定义、语法、应用场景等都非常重要,因此我们需要熟练掌握它们,才能更好地利用 Python 装饰器来提高工作效率。
