python中函数的执行流程和递归

函数执行流程:

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()


1) 全局帧中生成foo1,foo2,foo3,main函数对象

2) main函数调用

3)main中查找内建函数print压栈,将常量字符串压栈,调用函数,弹出栈顶

4)main中全局查找函数foo1压栈,将常量100,101压栈,调用函数foo1,创建栈帧.print函数压栈,字符串和变量b,b1压栈,调用函数,弹出栈顶,返回值.

5)main中全局查找foo2函数压栈,将常量200压栈,调用foo2,创建栈帧.foo3函数压栈,变量c引用压栈,调用foo3,创建栈帧.foo3完成print函数调用后返回.foo2恢复调用,执行print后,返回值.main中foo2调用结束弹出栈顶,main继续执行print函数调用,弹出栈顶.main函数返回.

更深层次的函数执行流程:


递归Recursion:

1.定义: 函数直接或者间接调用自身就是递归;它需要有边界条件,递归前进段,递归返回段;递归一定要有边界条件,当边界条件不满足的时候,递归前进,当边界条件满足的时候,递归返回.

   要求:递归一定要有退出条件,递归调用一定要执行到这个退出条件.没有退出条件的递归调用,就是无限调用;递归调用的深度不宜过身,但python对递归调用的深度做了限制,以保护解释器;超过递归调用的深度,抛出RecursionError : maxinum recursion depth exceeded 超出最大深度,用sys.getrecursionlimit()可以更改最大深度,但最好别动它啊.

    性能:循环稍微复杂一些,但只要不是死循环便可以多次迭代直至算出结果;fib函数代码极简易懂,但是只能获取到最外层的函数调用,内部递归结果都是中间结果,而且给定一个n都要进行近2n次递归,深度越深,效率越低,为获取斐波纳挈数列需要外面再套一个n次的循环,效率更低了.并且它还有深度限制,如果递归负载,函数反复压栈,栈内存很快就溢出了.

    间接递归:  通过别的函数调用了函数自身,但如果构成了循环递归调用是非常危险的,往往这种情况出现在代码复杂的情况下,所以要规范代码来避免这种递归.

    总结: 递归是一种很自然的表达,符合逻辑思维,其相对运行效率低,每一次调用函数都要开辟桟帧,递归有深度限制,如果递归层次太深,函数反复压栈,栈内存很快就溢出了;如果是有限次数的递归,可以使用递归调用,或者使用循环代替,循环代码稍微复杂一些,但是只要不是死循环都可以多次迭代直至计算出结果,且绝大多数递归都可以使用循环实现;即使递归代码很简洁,但是能不用则不用递归.

def foo1():
    foo2()
def foo2():
    foo1()
foo1()

2.递归的实践:

    1)斐波纳挈数列的打印:
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(5):
    print(fib(i),end =  ' ')

解析:fib(3)+fib(2)   

        fib(3)调用fib(3),fib(2),fib(1)

        fib(2)调用fib(2),fib(1)

        fib(1)是边界

        说通俗点就是return多少次1的问题

        每一次都要从头开始计算

        效率低下

方式二:

def num(x=0,y=1,n=1):
    n += 1
    x,y = y,x + y
    print(x,end = ' ')
    if n == 6:
        return
    num(x,y,n)

利用函数的默认值,将每次改变的默认值保存下来供下次使用,效率稍高

    2)求n的阶乘:

方式一:

def func(n=1,x=1):
    n += 1
    x = x*n 
    if n == 5:
        print(x)
        return
    func(n,x)

方式二:

def fac(n):
    if n == 1:
        return 1
    return n*fac(n-1)
方式三:
def fac1(n, p = 1):
    if n == 1:
        return p
    p *= n
    print(p)
    fac1(n-1,p)
    return p

方式四:

def fac1(n, p = 1):
    if n == 1:
        return p
    p *= n
    print(p)
    fac1(n-1,p)
    return p

方式五:

def fac2(n,p=None):
    if p is None:
        p=[1]
    if n == 1:
        return p[0]
    p[0] *= n
    print(p[0])
    fac2(n-1,p)
    return p

比较一下这几种方式的性能

    3)将一个数逆序放到列表中,例如1234:

方式一:

str1='1234'
lst=[]
length=len(str1)
for i in range(len(str1)):
    lst.append(int(str1[length-i-1]))

方式二:

def fnc(n,lst=[]):
    x=n%10
    n=n//10
    lst.append(x)
    if n//10 == 0:
        lst.append(n)
        print(lst)
        return
    fnc(n,lst)

    4)再解决一下猴子怎么吃桃

方式一:

x=1
for _ in range(1,10):
    x=2*(x+1)
print(x)

方式二:

def num(n=1,x=1):
    x = (x+1)*2
    n += 1
    if n == 10:
        print(x)
        return
    num(n,x)
num(n=1,x=1)
方式三:
def peach(days=1):
    if days == 10:
        return 1
    return (peach(days+1)+1)*2 #返回值
print(peach())




阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭