1. 装饰器介绍
装饰器是Python语言中的一种高级语法,是指把函数作为参数传入另一个函数中,用另一个函数来修饰原函数的行为,使原函数在不改变自身代码的情况下,实现特定的功能。
1.1 装饰器的示例
假设我们需要统计程序中每个函数的执行时间。我们可以在每个函数的开始和结束处记录时间,但这样做会使代码冗长而且难以维护。使用装饰器,我们可以统一管理所有函数的执行时间,并且不影响原函数的代码。
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__}() executed in {end_time - start_time:.5f}s")
return ret
return wrapper
@timer
def fun1(n):
for i in range(n):
pass
fun1(1000000)
上述代码定义了一个装饰器timer,用于统计被修饰函数的执行时间。在函数fun1上方添加@timer表示调用装饰器对该函数进行修饰。运行代码,输出:
fun1() executed in 0.05472s
我们可以看到,函数fun1的执行时间被正确记录了下来。
2. 递归介绍
递归是一种解决问题的方法,它通过将问题分解成子问题来解决。在递归过程中,函数会不断调用自身,直到达到终止条件才会停止。
2.1 递归的示例
计算阶乘是一个常见的递归示例。阶乘指对于正整数n,它的阶乘n!表示n*(n-1)*(n-2)*...*1。
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(5))
上述代码定义了一个函数factorial,用于计算n的阶乘。在函数中,若n=1则直接返回1,否则返回n乘以n-1的阶乘。运行代码,输出:
120
我们可以看到,函数factorial正确地计算了5的阶乘。
3. 装饰器结合递归的实现
3.1 递归函数加入装饰器
在实际开发中,递归函数有可能出现无限递归调用的情况。为了避免这种情况的发生,在递归函数中加入装饰器来限制递归深度就非常有必要了。
下面是一个计算斐波那契数列的递归函数:
def fib(n):
if n <= 1:
return n
else:
return fib(n-1) + fib(n-2)
我们知道,在计算斐波那契数列的时候,会出现大量的重复计算,这会导致程序的效率下降。为了避免这种情况的发生,我们可以使用装饰器来进行优化,装饰器的作用是将每个函数的结果缓存下来,如果下次调用时,参数相同,则直接返回缓存的结果。
def memo(func):
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
else:
result = func(*args)
cache[args] = result
return result
return wrapper
@memo
def fib(n):
if n <= 1:
return n
else:
return fib(n-1) + fib(n-2)
上述代码定义了一个装饰器memo,它用于优化斐波那契数列函数的递归计算。在函数fib上方添加@memo表示对该函数进行装饰。运行代码,输出:
print(fib(50))
print(fib(60))
print(fib(70))
12586269025
1548008755920
190392490709135
3.2 装饰器对递归深度的限制
递归函数在程序中的调用次数是不确定的,如果递归深度太大会导致程序崩溃。下面是一个简单的计算阶乘的递归函数:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(5))
我们可以通过添加装饰器来限制递归深度:
import sys
def depth_limited(max_depth):
def decorator(func):
def wrapper(*args, depth=0, **kwargs):
if depth > max_depth:
print(f"Recursion limit of {max_depth} exceeded!")
sys.exit()
return func(*args, depth=depth+1, **kwargs)
return wrapper
return decorator
@depth_limited(10)
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(1000))
上述代码定义了一个装饰器depth_limited,它用于在递归超过最大深度时终止函数。在函数factorial上方添加@depth_limited(10)表示使用装饰器对函数进行修饰,限制递归深度为10。运行代码,输出:
Recursion limit of 10 exceeded!
4. 总结
本文介绍了Python中的装饰器和递归的基本概念和用法,并给出了具体的代码实现。通过安排好递归调用顺序,我们可以让程序更加高效地运行。而通过限制递归深度等方式,我们可以避免程序因递归过深而崩溃。
Python装饰器结合递归原理的实现,让我们看到了递归和装饰器的强大功能,同时也为我们提供了一种新思路来优化程序的性能。