
def foo1(b,b1=3):
print("foo1 called",b,b1)
def foo2(c):
foo3(c)
print("foo2 called", c)
def foo3(d):
print("foo3 called", d)
def main():
print("main called")
foo1(100,101)
foo2(200)
print("main ending")
main()
====================run_result==============
main called
foo1 called 100 101
foo3 called 200
foo2 called 200
main ending
【解析】
全局模块中定义了foo1、foo2、foo3、main四个函数
main函数调用
语句:print("main called")
1.main函数中查找内建函数print压栈,
2.将字面常量字符串压栈,调用函数后弹出栈顶
语句:foo1(100,101)
1.main中全局查找函数foo1压栈,将常量100和101压栈,
2.调用函数foo1,创建栈帧
3.print函数压栈,字符串和变量b,b1压栈,调用函数,弹出栈顶,返回值
语句:foo2(200)
1.main中全局查找函数foo2压栈,将常量200压栈
2.调用函数foo2,创建栈帧
3.foo3函数压栈,变量c引用压栈
4.调用foo3,创建栈帧,foo3完成后print调用并返回,弹出栈顶
5.foo2恢复调用,执行print后,返回值
6.main中foo2调用结束弹出栈顶
7.main继续执行print函数调用,弹出栈顶,main函数返回
补充:栈的简单介绍
1.内存中是分栈和堆的
2.对于函数来说,用到的是栈,就相当于落盘子,只能从上面拿,不能从底部抽。
3.栈的原则:先进后出,后进先出
4.如果函数A在调用后还未释放的情况下,需要调用新的函数B,可以先将A函数保存后压入栈中,再调用B函数的数据压栈,代码执行后数据释放完毕,即可将函数B弹出栈顶,然后夹在A函数,继续执行A函数的代码
程序执行过程中,压栈的情况详见下方截图

def foo(b,b1=1):
print("foo1 called",b,b1)
foo2(1)
def foo2(a):
pass
foo(2)

【foo1函数的内存执行步骤】
pre = 0
cur = 1
print(pre,cur,end=" ")
n=4
for i in range(n-1):
pre,cur = cur,pre+cur
print(cur,end=" ")
#函数定义
def fib(n):
return 1 if n<2 else fib(n-1)+fib(n-2)#三元表达式
#函数调用
for i in range(10):#i=0,1,2,3,4
print(fib(i),end=" ")
【解析】
return 1
RecursionError: maximum recursion depth exceeded in comparison 超出最大深度sys.getrecursionlimit(),可以修改正这个值,使用sys.setrecursionlimit()函数,括号中传入要设置的深度值,但是,一般情况下,请不要修改这个值import sys
def fib(n):
if n<2:
return 1
else:
return fib(n-1)+fib(n-2)
a = fib(4)
print(a)
print(sys.getrecursionlimit())
================run_result===============
5
1000 #表示递归的最大深度是1000
递归的性能有以下特点:
【改进策略】
pre = 0
cur = 1 #numb 1
print(pre,cur,end= " ")
def fib(n,pre=0,cur =1):#首次进来,pre=0,cur=1
pre,cur = cur,pre + cur
print(cur,end=" ")
#前面的数pre已经计算过了,直接打印后面的cur,即计算出的两数之和
if n ==2:#n=2推出循环
return #返回None
fib(n-1,pre,cur)
#执行完以后,n-1,将上面计算之后的pre和cur作为实参传入
fib(10)
==============run_result==========
0 1 1 2 3 5 8 13 21 34 55
【注意】
fib(n-1,pre,cur)已经执行完毕(print打印),因此之前的函数就隐含返回了一个return None,因此之前调用函数的返回值就是Nonedef foo():
foo2()
def foo2():
foo()
foo()
#初始做阶乘题目时,可以先将for循环写出来
#使用递归,传入参数时,传参是n-1,因此是按照range函数的倒序传参的
#也就是说:传入参数的顺序是5,4,3,2,1
#循环如下:
n=10
num = 1
for i in range(n,0,-1):
if i ==0:
num = 1
else:
num *= i
print(num)
#自己根据for循环代入递归写的解题代码
def get_jc(n,jc_r=1):#默认阶乘的初始值为1,如果为0,乘积时所有的结果全部是0
if n ==0:#当n=0为1时,阶乘的数值为1,因此直接在末尾乘以1
jc_r *= 1
else:
jc_r *= n#n不为0,阶乘的计算方式是:5*4*3*2*1
if n == 0:#这里是递归函数的退出条件,n=0就不需要往下执行了
print(jc_r)#打印所有数值乘积之后的阶乘
return
get_jc(n-1,jc_r)#递归调用函数
get_jc(10)
#递归实现的其他方式:
def jc_3(n,jc_v=1):
jc_v *= n
if n ==1:
return jc_v
return jc_3(n-1,jc_v)
a=jc_3(5)
print(a)
=======================run_result================
3628800
3628800
3628800
【jc_3代码解析】
#初始做阶乘题目时,可以先将for循环写出来,倒序的for循环如下:
l_d = [4,6,8,3]#原列表
e = len(l_d)
l_n = [1]* e
#新列表,这句话的意思是形成一个长度为e的新列表,列表的元素都是1
#注意,使用这种方式,列表中元素的内存地址默认指向同一个位置,引用类型,需要注意
for i in range(e,0,-1):
l_n[e-i] = l_d[i-1]
print(l_n)
#逆序放入列表的递归方式:
l_d = [4,6,8,3]
e = len(l_d)
l_n = [1] * e
def re_l(a=e):
l_n[e-a] = l_d[a-1]
if a == 1:
return
re_l(a-1)
re_l()
print(l_n)
print("****************** 第二种方式 ************")
#也可以将这种改成升序的形式,升序的for循环是:
l_d = [4,6,8,3]
e = len(l_d)
l_n = [1]* e
for i in range(e):
l_n[i] = l_d[e-1-i]
print(l_n)
#将其给成递归,就是:
l_d = [4,6,8,3]
e = len(l_d)
l_n = [1] * e
def re_l(a=0):
l_n[a] = l_d[e-1-a]
if a == e-1:
return
re_l(a+1)
re_l()
print(l_n)
===================run_result==================
[3, 8, 6, 4]
[3, 8, 6, 4]
[3, 8, 6, 4]
[3, 8, 6, 4]
【解析】
l_n[e-i] = l_d[i-1],这句话,是发现规律之后写的,倒序时,3对0,2对1,1对2.,0对3,因此当i在4,3,2,1循环递减是,e-i的索引对应0,1,2,3,新列表需要对应的索引是:3,2,1,0,因此索引就是i-1【思考】
def str_d(num,flag = []):
if num:
flag.append(num[len(num)-1])#根据索引获取字符串中最后一个元素
str_d(num[:len(num)-1])#传入的参数为去掉最后一个元素之后的字符串
return flag
print(str_d(str(43299)))
===============run_result=================
['9', '9', '2', '3', '4']
猴子吃桃子:猴子摘了n个桃子,第一天吃了一半多一个,第二天吃剩下的一半多一个,以此类推,到了第10天就剩下一个,请问,猴子最初摘了多少个桃子?
#for循环代码
n=1
for i in range(1,10):
n=(n+1)*2
print(n)
#递归用法
#注意:n相当于for循环中的i,a相当于for循环中的n,计算桃子个数
def tz(a,n=1):
a = (a+1)*2
if n == 9:
print(a)
return
tz(a,n+1)
tz(1)
===================run_result===================
1534
1534
函数的相互调用是指在一个函数中调用另外一个函数,例如
def print_msg(content):
print('我想说 :{0}'.format(content))
def learn_language(name):
print("我正在学{}语言".format(name))
# 在一个函数中调用另外一个函数,“很难”为content的值
print_msg('很难')
learn_language('英语')
***********************run_result******************
我正在学英语语言
我想说 :很难
def print_msg(content):
print('我想说 :{0}'.format(content))
def learn_language(name,content):
print("我正在学{}语言".format(name))
# 在一个函数中调用另外一个函数,“很难”为content的值
#print_msg('很难')
print_msg(content)#调用时参数化被调用函数的参数
learn_language('Python','好难')
***********************run_result******************
我正在学Python语言
我想说 :好难
需要注意:
**python语言的执行是从上而下的,如果调用函数放在两个函数之间,会报错,**例如以下截图

def add(x,y):
return x+y
print(add(4,5))