• 递归函数


    变量名解析原则LEGB
    local 本地作用域,局部作用域的命名空间,函数调用时创建,调用结束消亡
    Enclosing,python2.2时引入嵌套函数,实现了闭包。就是函数嵌套的外部函数的命名空间
    Global,全局作用域,即一个模块的命名空间,模块被import时创建,解释器退出消亡
    Build-in ,内置模块的命名空间生命周期从python解释器启动时创建到解释器退出时消亡。例如print(open),print和open都是内置的变量
     
    所以名词查找顺序 就是L-->E-->-->G-->B
      
    函数递归:
     
    例子(1,1):
    def foo1(b,b=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,1)分析:
     
    全局帧中生成foo1,foo2,foo3main函数对象
    1.main函数调用
    2.main中查找 内建函数 print压栈,将常量字符串压栈,调用函数,弹出栈顶
    3.mani函数中全局查找foo1压栈,将常量100,101压栈,调用函数foo1,创建 栈帧,->print函数压栈,字符串常量压栈,调用函数,弹出栈顶
    4.main函数中全局查找foo2压栈,将常量200压栈,调用函数foo2;创建栈帧,foo3函数压栈,变量c引用压栈,调用函数foo3 创建栈帧,foo3完成print函数调用后返回foo2恢复调用,执行print后,返回值。main中foo2调用结束弹出栈顶,main函数继续向后执行print函数调用,弹出栈顶。main函数返回
     
    自我理解:
    main函数调用->调用print函数返回字符串->查找foo1函数并传参并调用函数print返回字符串->查找foo2函数并传参调用->foo2函数中含有foo3函数调用->foo3函数调用print函数并返回字符串-> 最后main函数调用print函数返回
     
    利用pychrm 断点判断函数嵌套使用是否正常
     
         递归Recursion:
    函数直接或者间接调用自身就是递归;          (自己调用自己)
    递归要有边界条件,递归前进段,递归返回段
    递归一定要边界条件
    当条件不满足时,递归前进
    当条件满足的时候,递归返回
     
    利用递归实现斐波那契数列:
    for循环实现
    (1,2)
    pre=0
    cur=1  第一个数
    print(pre,cur,end=' ')
     n=4
    for i in range(n-1):
         pre,cur=cur,pre+cur
         print(cur,end=' ')
     
    递归调用自实现
    斐波那契数列的数学公式:
    (1,2,1)
    F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)
    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(2)是边界,每一个递归函数都必须有一个边界
    利用边界来计算,但是效率很低,公式那里递归了很多次
     
    总结:
    递归要求:
    一定要有退出条件,没有递归条件,就无限循环
    递归深度不宜过深,否则会超出限制
    查询当前最大递归深度 sys.getrecusionlimit()
     
    递归的性能:
    循环稍微复杂,不是死循环,就能多次迭代出结果
    递归 有深度限制,函数反复压栈,内存溢出快
     
     
    递归斐波那契数列的性能改进:
    (1,3)
    def fib(n,pre=0,cur=1):
         pre,cur=cur,pre+cur
         print(cur,end=' ')
         if n==2:
              return
         fib(n-1,pre,cur)
    fib(n)
     
    代码(1,3)分析:
    上述的fib函数和循环的思想类似
    参数n是边界条件,用n来计数
    上一次的计算结果直接作为函数的实参
    效率高,和循环性能相近,但是递归深度有限
     
    间接递归:
    def foo1():
         foo2()
     
    def foo2():
         foo1():
     
    foo1:
     
    间接递归,是通过别的函数调用函数自身;
    得注意循环递归,代码越复杂,越容易发生,所以代码得规范使用,避免出错
     
    递归总结:
    递归是一种自然表达,符合逻辑
    递归相对运行效率低,每一次都调用函数都要开辟栈帧
    递归有深度限制,栈内存容易溢出
    大部分递归都可以用循环实现
    能不要则不用递归
     
    递归习题:
    算阶乘
    def foo(n,m=1):
         m*=n
         if n==1:
              return m
         return foo(n-1,m)
    foo(5)
     
    将1234倒叙打印
    p=1234
    def foo(n,m=[]):
        m.append(str(p)[n-1])
        if n==1:
            return m
        return foo(n-1)
    foo(len(str(p)))
     
    猴子吃桃:
    def peach(day=9,sum=1):
        sum=(sum+1)*2
        day-=1
        if day==0:
            return sum
        return peach(day,sum)
     
     
     
  • 相关阅读:
    vue组件常用传值
    定时器的暂停,继续,刷新
    element-ui表格带复选框使用方法及默认选中方法
    git创建分支
    CAS协议原理与代码实现(单点登录 与 单点登出的流程)
    Java-技术专区-Files类和Paths类的用法
    Java-技术专区-Java8特性-parallelStream
    ELK日志系统环境搭建-6.x系列
    Spring系列-Spring Aop基本用法
    Spring-框架系列-SpringIOC容器初始化
  • 原文地址:https://www.cnblogs.com/spidermansam/p/7675471.html
Copyright © 2020-2023  润新知