Python中的装饰器函数详解和用法
装饰器(Decorator)是 Python 中一个非常重要的语法特性,它可以在不改变原有函数代码的基础上,对函数进行增强或者添加额外的逻辑,同时也可以用来对函数进行统计、日志记录等操作,极大地提高了编程的灵活性和可维护性。
装饰器函数是一种特殊的函数,它的参数是一个函数对象或者是一个可调用对象,它的返回值也是一个函数对象。通过装饰器函数可以在函数执行前后进行一些额外的操作,例如计算函数执行时间,检查函数参数或者返回值等。
下面我们来看一个简单的实例,使用装饰器函数计算函数执行时间:
import time
def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print("Function {} execution time: {}".format(func.__name__, end-start))
return result
return wrapper
@time_it
def factorial(n):
"""
计算阶乘
"""
if n == 0:
return 1
else:
return n * factorial(n-1)
factorial(5)
在上面的代码中,我们定义了一个名为 time_it 的装饰器函数,它的参数是一个函数 func。在函数内部定义了名为 wrapper 的函数,它接收任意数量和类型的参数和关键字参数,调用 func 并记录了函数的开始时间和结束时间,并输出函数的执行时间。
在进行阶乘运算时,在函数定义前面加上 @time_it 装饰器即可在执行阶乘函数时自动执行装饰器函数。
除了计算执行时间外,我们还可以使用装饰器函数来完成一些其他的任务,例如:
### 1. 记录日志
使用装饰器函数来记录函数的调用次数及参数信息。
def log_it(func):
count = 0
def wrapper(*args, **kwargs):
nonlocal count
count += 1
print("Calling function {}: count={}, args={}, kwargs={}".format(func.__name__, count, args, kwargs))
return func(*args, **kwargs)
return wrapper
@log_it
def add_numbers(a, b):
"""
计算两个数的和
"""
return a + b
add_numbers(2, 3)
add_numbers(4, 5)
### 2. 检查函数参数和返回值
如果要对函数的参数和返回值进行检查,则可以编写一个装饰器函数来实现。
def check_input_output(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, int):
raise TypeError("Argument {} is not an integer.".format(arg))
result = func(*args, **kwargs)
if not isinstance(result, int):
raise TypeError("Result {} is not an integer.".format(result))
return result
return wrapper
@check_input_output
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
factorial("5")
### 3. 缓存函数结果
如果一个函数的输入输出相同,那么它的输出结果也应该是相同的。因此,我们可以使用装饰器函数来缓存函数的结果,从而避免执行重复计算。
def memoize(func):
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
else:
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
factorial(4)
在上面的例子中,我们定义了一个名为 memoize 的装饰器函数,使用字典来缓存函数的执行结果,从而避免重复计算。
总结一下,通过装饰器函数可以在函数执行前后进行一些额外的操作,例如计算函数执行时间、记录函数调用次数和参数、缓存函数执行结果等。使用装饰器函数可以避免在每个函数中都编写重复的代码,并提高了代码的复用性和可维护性。在 Python 中有很多方便好用的内置装饰器,例如 @classmethod、@staticmethod、@property 等,这些装饰器函数可以让代码更加简洁和易于理解。
