使用装饰器在Python中扩展函数的功能
Python的装饰器是一个很强大的特性,使用它可以很方便的扩展函数的功能。装饰器并不是一个新的语法,而是一个语法糖。使用装饰器可以在不改变函数代码的情况下,扩展其功能。
装饰器是一个函数,它接收一个函数作为参数,并返回一个新的函数。装饰器的主要作用是在不改变函数原有功能的前提下,增加一些新的功能。装饰器可以用来实现很多实用的特性,比如日志记录、性能统计、缓存等。
装饰器的语法格式是在函数定义前加上@符号,后面紧接着装饰器函数的名称。例如:
@decorator_function
def my_function():
pass
装饰器函数接收原始函数作为参数,并返回一个新的函数,它通常会包含一个内部函数,用来包裹原始函数:
def my_decorator(func):
def wrapper():
# 执行一些操作,不影响原始函数
print('wrapper executed this before {0}()'.format(func.__name__))
# 调用原始函数
func()
# 执行一些操作,不影响原始函数
print('wrapper executed this after {0}()'.format(func.__name__))
return wrapper
上述代码中,my_decorator是一个装饰器函数,它接收一个函数作为参数,返回一个新的函数wrapper。wrapper函数包含了一些额外的操作,例如记录日志或缓存结果,然后调用原始函数并返回结果。
下面是一个例子,演示如何使用装饰器实现一个简单的缓存系统:
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 fibonacci(n):
if n < 2:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
上述代码中,memoize是一个装饰器函数,它接收一个函数作为参数,返回一个新的函数wrapper。wrapper函数包含了缓存逻辑,它首先检查是否已经有了缓存结果,如果有则直接返回;否则调用原始函数,并将结果存入缓存。
在实际使用中,装饰器是可以叠加使用的。例如,可以同时使用多个装饰器,实现多个功能的扩展:
@logger
@memoize
def fibonacci(n):
if n < 2:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
这种方式会先调用memoize装饰器,然后将结果传递给logger装饰器。
同时,装饰器还支持参数。在装饰器函数内部也可以定义一些参数,并在内层函数中使用它们。例如:
def repeat(num):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('Repeat {0}'.format(i+1))
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(3)
def say_hello():
print('Hello!')
say_hello()
上述代码中,repeat是一个带有参数的装饰器函数,它接收一个整数作为参数,然后返回一个新的装饰器函数decorator_repeat。decorator_repeat接收一个函数作为参数,并返回一个新的函数wrapper。wrapper函数用来重复执行传入的函数,并输出重复次数。在使用时,可以像下面这样调用:
say_hello()
输出结果如下:
Repeat 1 Hello! Repeat 2 Hello! Repeat 3 Hello!
总结:
Python的装饰器是一个很强大的特性,使用它可以很方便的扩展函数的功能。装饰器可以在不改变函数代码的情况下,增加一些新的功能,比如日志记录、性能统计、缓存等。装饰器可以叠加使用,也支持参数。对于需要扩展功能的函数来说,使用装饰器可以使代码更简洁,更易于维护。
