初识递归:
递归的定义——在一个函数里再调用这个函数本身
在一个函数里再调用这个函数本身,这种魔性的使用函数的方式就叫做递归。
递归的最大深度——997
正如你们刚刚看到的,递归函数如果不受到外力的阻止会一直执行下去。但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属于它自己的名称空间,如果一直调用下去,就会造成名称空间占用太多内存的问题,于是python为了杜绝此类现象,强制的将递归层数控制在了997(只要997!你买不了吃亏,买不了上当...).
拿什么来证明这个“997理论”呢?这里我们可以做一个实验:
def foo(n):
print(n)
n += 1
foo(n)
foo(1)
看到这里,你可能会觉得递归也并不是多么好的东西,不如while True好用呢!然而,江湖上流传这这样一句话叫做:人理解循环,神理解递归。所以你可别小看了递归函数,很多人被拦在大神的门槛外这么多年,就是因为没能领悟递归的真谛。而且之后我们学习的很多算法都会和递归有关系。
递归:
在一个函数里面调用自己
默认的递归最大限度 997
不要修改默认的递归最大限度
往往 递归 都是 和循环挂在一起的
人理解循环 神理解递归
使用递归的特点:
需要多次函数调用,并且每次调用都拥有相同的特点,各个之间有依赖性,适合用递归。
递归函数最常用的场景,它有一个参数,根据你的一系列计算,可以将这个参数进行一些简化,且你后续的计算过程跟你之前的计算过程完全相似,这种情况就适合用递归函数。
一个递归函数,如果没有条件的限制的话,它无法结束。
例一:
Alex的年龄:
#多大了alex,我不告诉你,alex比egon大两岁 44+2
#egon多大了,我不告诉你,egon比wusir大两岁 42+2
#wusir多大了,我不告诉你,wusir比金鑫大两岁 40+2
#金鑫40了
翻译成程序语言:
# age(1) n = 1 age(2)+2
# age(2) n = 2 age(3)+2
# age(3) n = 3 age(4)+2
# age(4) n = 4 40
def age(n): if n == 4: #递归结束的条件 return 40 else: return age(n+1) + 2 #返回其本身的函数调用 print(age(1)) 输出: 46
运行过程:
# def age(1): # if n == 4: # return 40 # return age(1+1) + 2 # def age(2): # if n == 4: # return 40 # return age(2+1) + 2 # def age(3): # if n == 4: # return 40 # return age(3+1) + 2 # def age(4): # if n == 4: # return 40 # return age(n+1) + 2
例二:
阶乘的计算:
阶乘的定义:什么叫阶乘? 7 #7*6*5*4*3*2*1
def f(n): if n == 1: #递归结束的条件 return 1 else: return n*f(n-1) #返回其本身的函数调用 print(f(3)) 输出: 6
运行过程:
def f(3): if 3 == 1: return 1 else: return 3*f(2) def f(2): if 2 == 1: return 1 else: return 2 * f(1) def f(1): if 1 == 1: return 1 else: return n*f(n-1)
例三:
斐波那契数列
1,1,2,3,5,8,13....
求斐波那契数列中第10位是多少
# n = 10
# f(10) = f(8)+f(9)
def fib(n): if n == 1 or n == 2: #递归结束的条件 return 1 else: return fib(n-1)+fib(n-2) #返回其本身的函数调用 print(fib(10)) 输出: 55
运算过程:
fib(3): def fib(3): if 3 == 1 or 3 == 2: return 1 return fib(2)+fib(1) def fib(2): if 2 == 1 or 2 == 2: return 1 return fib(n-1)+fib(n-2) def fib(1): if 1 == 1 or 1 == 2: return 1 return fib(n-1)+fib(n-2)
例四:
运用二分法在列表中查找一个值:
#参数传递
#返回值的问题
#找不到值的人体
#参数太多的问题
def find_2(l,aim,start=0,end=None): #[2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88] if end == None:
end = len(l) - 1 if start <= end: mid = (end-start) // 2 + start if l[mid] > aim: ret = find_2(l,aim,start,mid-1) #返回这个函数调用 return ret elif l[mid] < aim: ret = find_2(l,aim,mid+1,end) #返回这个函数调用 return ret else: return aim,mid else: print('找不到这个值')
运行输出:
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88] print(find_2(l,17)) 输出: 找不到这个值 None
运行输出二:
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88] print(find_2(l,30)) 输出:
(30, 9)
例五:
地区的三级调用:
menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': {}, } def menu_3(menu): while True: #当输入对的,就进下一层,输入不对,再输一次 for key in menu: print(key) #北京上海山东 choice = input('选择 : ') #北京 if choice == 'q' or choice == 'b': return choice elif choice in menu and menu[choice]: #北京 in menu borq = menu_3(menu[choice]) if borq == 'q': return 'q' menu_3(menu)