Python装饰器-实现函数的增强功能
Python装饰器是Python语言中一种非常强大的编程技术,它可以在不改变原有代码的前提下,为函数或类添加新的功能。与函数参数一样,Python装饰器是由@符号后面跟着一个函数名组成的。Python装饰器的灵活性和可复用性使其成为Python中非常重要的编程技术之一。
一个装饰器函数的定义通常包括以下几个步骤:
1. 定义一个装饰器函数,以函数作为参数,并返回另外一个函数。
2. 在包装函数中,定义需要增强功能的代码(装饰器的本体)。
3. 在包装函数的前面加上@符号,以将包装函数绑定到需要增强功能的函数上。
Python装饰器可以将一些固定的功能作为一个公共的框架,让不同的函数能够共享这些固定功能。在写Python程序时,有时我们会发现需要给某个函数添加额外的功能,比如记录函数的调用次数、打印函数的输入输出、检查参数的类型等等。使用Python装饰器,我们可以为这些功能都编写一个独立的装饰器函数,并在需要的函数中调用这个装饰器函数,从而实现这些功能的增强。
下面我们来介绍几个常用的Python装饰器。
装饰器用法1:函数的运行时间计时
有时候我们需要统计某个函数的执行时间,来判断其性能是否优良。下面是一个计时器的装饰器函数:
import time
def performance_timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print("Function", func.__name__, "took", end_time - start_time, "seconds to run.")
return result
return wrapper
下面是一个示例函数:
@performance_timer
def test_function():
time.sleep(1)
在这个示例函数中,我们让函数等待1秒钟。我们可以使用Python装饰器为这个函数增加一个计时功能,以打印函数的执行时间:
test_function()
输出结果:
Function test_function took 1.0000293254852295 seconds to run.
装饰器用法2:参数类型检查
有时候我们需要检查函数参数的类型,以避免函数在执行时出现输入错误的情况。下面是一个参数类型检查的装饰器函数:
def arg_types(*types):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(len(types)):
if types[i] != type(args[i]):
raise TypeError("Argument {} should be of type {}".format(i+1, types[i]))
return func(*args, **kwargs)
return wrapper
return decorator
下面是一个示例函数:
@arg_types(int, float, str)
def test_func(a, b, c):
print("a=", a)
print("b=", b)
print("c=", c)
在这个示例函数中,我们指定了三个参数类型int、float和str。我们可以使用Python装饰器为这个函数增加一个参数类型检查的功能,以保证函数的输入参数的正确性:
test_func(1, 1.1, "Hello")
输出结果:
a= 1 b= 1.1 c= Hello
接下来我们来看一个参数输入错误的情况:
test_func("abc", 1.1, "Hello")
程序会抛出一个TypeEror异常:
TypeError: Argument 1 should be of type <class 'int'>
装饰器用法3:记录函数执行日志
有时候我们需要记录函数的执行日志,以便于日后追踪程序异常。下面是一个记录函数执行日志的装饰器函数:
def logger(func):
import logging
logging.basicConfig(filename='{}.log'.format(func.__name__), level=logging.INFO)
def wrapper(*args, **kwargs):
logging.info('Call function {}'.format(func.__name__))
result = func(*args, **kwargs)
logging.info('Function {} finished'.format(func.__name__))
return result
return wrapper
下面是一个示例函数:
@logger
def test_logger(a, b, c):
pass
我们可以使用Python装饰器为这个函数增加一个记录函数执行日志的功能,以便日后更好的追踪程序异常:
test_logger(1, 2, 3)
函数执行后,我们会得到一个名为test_logger.log的日志文件,其中包含一些关于test_logger()函数调用的信息。
装饰器用法4:实现函数缓存
有些函数的计算量很大,每次调用都需要重新计算,如果能够对函数的计算结果进行缓存,就可以避免重复计算,提高程序的执行效率。下面是一个实现函数缓存的装饰器函数:
def cache(func):
cache_dict = {}
def wrapper(*args):
if args in cache_dict:
return cache_dict[args]
else:
result = func(*args)
cache_dict[args] = result
return result
return wrapper
下面是一个示例函数:
@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
在这个示例函数中,我们通过递归的方式计算斐波那契数列。我们可以使用Python装饰器为这个函数增加一个缓存功能,以避免对已经计算过的参数进行重复计算:
fibonacci(10)
输出结果:
55
接下来我们来看一个重复计算的情况:
fibonacci(10)
由于之前已经计算过fibonacci(10),程序直接获取缓存中的结果,因此不会执行重复计算,输出结果仍然是55:
55
这么说来,Python装饰器是一个非常强大和灵活的编程技术。它不仅可以为函数添加额外的功能,还可以将多个装饰器组合起来使用,以实现更为强大的功能增强。同时,在Python 3.0中,装饰器还可以用于类的定义和方法的增强,使其更加通用。通过学习Python装饰器,我们可以更加灵活地编写Python程序,提高编程效率和代码复用性。
