Python的装饰器函数:用法和实例
Python的装饰器是一种在不修改它本身的情况下增加其功能的函数或类。在一个函数或类的定义之前使用@符号和装饰器函数名称,可以将其装饰上其他功能。Python的装饰器可以帮助我们在不改变原有代码的基础上实现横向扩展,提高代码的可重用性和可维护性。
下面我们来具体介绍一下Python的装饰器函数的用法和实例。
1. 带参数的装饰器
在Python中,装饰器函数可以带参数。例如,可以定义一个带参数的装饰器函数,实现多个装饰器的功能,例如对函数运行时间进行统计、打印函数错误信息等。
下面是一个例子:
import time
def time_count(logger):
def decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
logger("the function %s run for %d seconds" % (func.__name__, (end_time - start_time)))
return result
return wrapper
return decorator
@time_count(logger=print)
def test_func():
time.sleep(1)
test_func()
在这个例子中,我们定义了一个函数time_count,它接受一个参数logger,logger是一个函数,用来打印日志。它返回一个decorator函数,用来装饰需要进行时间统计的函数。
decorator函数中定义一个wrapper函数,wrapper函数可以接受任意数量任意类型的位置参数和关键字参数。wrapper函数会先记录当前时间,再调用原函数(即需要进行时间统计的函数),记录函数运行时间,最后调用logger函数,输出函数运行时间。wrapper函数返回原函数的运行结果。
在test_func函数上使用带参数的装饰器time_count,可以接收参数logger,打印函数运行时间。
2. 修饰类方法的装饰器
Python中的功能强大的类装饰器,可以为一个类添加新的方法或修改原有方法的功能。下面是一个例子,我们定义一个修饰类方法的装饰器,为类方法添加一个prefix参数:
def add_prefix(prefix):
def decorator(func):
def wrapper(self, *args, **kwargs):
return prefix + func(self, *args, **kwargs)
return wrapper
return decorator
class MyClass:
def __init__(self, value):
self.value = value
@add_prefix(prefix='Hello, ')
def my_method(self):
return str(self.value)
instance = MyClass(value='world')
print(instance.my_method())
在这个例子中,我们定义了一个装饰器函数add_prefix,它接受参数prefix,返回一个decorator函数。decorator函数会包装原有的类方法,通过在方法前面添加prefix来扩展实例的方法。
MyClass的实例instance在调用my_method方法时,会先调用add_prefix方法包装my_method方法,返回一个修改过的new_method方法,再调用new_method方法,实现在my_method方法前加上'Hello, '的效果。
3. 嵌套装饰器的用法
Python中的装饰器可以嵌套使用。下面是一个例子,我们定义了一个嵌套装饰器的函数,来实现对序列类型数据进行缓存的装饰器:
from functools import wraps
def cache_decorator(func):
cache = {}
@wraps(func)
def wrapper(*args):
if args in cache:
return cache[args]
else:
result = func(*args)
cache[args] = result
return result
return wrapper
def list_cache_decorator(func):
@cache_decorator
def wrapper(*args):
if isinstance(args[0], list):
args = tuple(args[0])
return func(*args)
return wrapper
@list_cache_decorator
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
print(factorial([5]))
在这个例子中,我们定义了两个装饰器函数:cache_decorator和list_cache_decorator。其中list_cache_decorator是一个嵌套装饰器,调用了cache_decorator函数来实现对序列类型数据进行缓存。
cache_decorator函数使用了一个字典对象cache,用来缓存原函数factorial的运行结果。如果原函数已经被调用过,且参数相同,直接返回缓存结果即可。如果缓存区没有结果,则调用原有的函数,并将结果更新到缓存区。
list_cache_decorator函数调用了cache_decorator函数,并使用了Python中内置的functools.wraps函数来将包装的函数wrapper的属性还原为原函数factorial的属性,这样就可以在包装函数wrapper中通过isinstance函数来判断参数是否是序列类型,并将序列类型的参数转化为tuple类型的参数,以便放入缓存区。最后返回了包装的函数wrapper。
在Python中,装饰器的用法非常灵活,它不仅可以增加函数的功能、调整函数的参数、还可以增加类的功能,使得代码实现起来更加简单和优雅。 在日常开发中,我们可以根据业务需求,结合装饰器的特性,实现不同的功能模块。
