递归调用
在调用一个函数的过程中,直接或间接调用了该函数本身。
1. 直接调用的栗子:
def foo():
print('hello, python')
foo()
foo() # 执行foo函数,直接调用本身,并且无无限递归下去,直接报错
- 间接调用的栗子:
def fxx():
print('from xx')
foo()
def foo():
print('from oo')
fxx()
foo() # # 执行foo函数,调用fxx,fxx调用foo,并且无无限递归下去,直接报错
查看递归设置
import sys
print(sys.getrecursionlimit()) # 1000 => python3 中默认最大递归次数
sys.setrecursionlimit() # 设置递归次数
递归的特点
- 递归必须有一个明确的结束条件,比如
if ...: return
l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]
# 取出数列的所有值
def show(l):
for i in l:
if isinstance(i, list): # 结束条件:是列表就继续,如果不是列表,就执行下面的打印
show(i)
else:
print(i)
show(l)
# 问一个人的年龄,这个人比下一个人大两岁,下一个人比下下一个人大两岁......直到第五个人说他18岁
def age(n):
if n == 1: # 明确的结束条件
return 10
else:
return age(n-1)+2
print(age(5))
def foo(n):
if n == 1: # 设置明确的结束条件。
return
print('from oo',n)
foo(n-1)
- 递归的两个阶段:
- 递推:到某个阶段,该阶段返回一个值
- 回溯:从那个阶段回溯
- 没进入更深一次递归时,问题规模减少。
- 递归效率不高。
- 应用场景:知道结束的条件,但不确定循环次数。
递归与二分法
# 递归与二分法(每次问题规模缩小一半)
data = []
for i in range(35):
data.append(i)
# 定义一个函数,输入一个数字,判断是不是在这个有序数列里面。
# 如果挨个找,可能把数列遍历完,效率低。
def search(num, data):
print(data)
if len(data) > 1: # 防止只有一个元素时还未找到,继续二分将对这个元素进行无尽的循环。
mid_index = int(len(data)/2)
mid_value = data[mid_index]
if num > mid_value:
data = data[mid_index:]
search(num, data)
elif num < mid_value:
data = data[:mid_index]
search(num, data)
else:
print('find it')
return # 找到了,结束。
else:
if data[0] == num:
print('find it')
else:
print('not exist')