zoukankan      html  css  js  c++  java
  • 递归函数,匿名函数

    先来看一下函数的执行流程:

    http://pythontutor.com/visualize.html#mode=edit  #这个网站可以帮到你;

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

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

    main函数调用;查找内建函数print压栈,将常量字符串压栈,调用函数,执行完成后弹出栈顶;

    main中全局查找函数foo1压栈,将常量100,101压栈,调用函数foo1,创建栈帧,print函数压栈,字符串和变量b,b1压栈,调用函数,执行完成后弹出栈顶;

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

    简单说下我的理解:

    函数嵌套时,外层函数调用压栈,在调用内层函数时压栈外层函数的进度,创建新的栈帧,后续依然,执行完成以后一层一层弹出;

    递归函数

    函数直接或间接调用自身就是递归;

    递归需要有退出条件;

    递归调用深度不宜过深,python对递归调用深度做了限制,默认是1000,超过递归深度限制,抛出:RecursionError: maxinum recursion depth exceeded

    可以通过sys模块下的sys.getrecursionlimit()来更改;

    递归调用对比:

    import datetime
    # Fib Seq
    start = datetime.datetime.now()
    pre = 0
    cur = 1 # No1
    print(pre, cur, end=' ')
    n = 35
    # loop
    for i in range(n-1):
        pre, cur = cur, pre + cur
        print(cur, end=' ')
    delta = (datetime.datetime.now() - start).total_seconds()
    print(delta)
    
    # Fib Seq
    start = datetime.datetime.now()
    pre = 0
    cur = 1 # No1
    print(pre, cur, end=' ')
    # recursion
    def fib1(n, pre=0,cur=1):
        pre, cur = cur, pre + cur
        print(cur, end=' ')
        if n == 2:
            return
        fib1(n-1, pre, cur)
    
    fib1(n)
    delta = (datetime.datetime.now() - start
             ).total_seconds()
    print(delta)
    
    start = datetime.datetime.now()
    def fib2(n):
        if n < 2:
            return 1
        return fib2(n-1) + fib2(n-2)
    
    for i in range(n):
        print(fib2(i), end=' ')
    delta = (datetime.datetime.now() - start).total_seconds()
    print(delta)
    

    递归性能(菲波那切数列):

    递归:

    import datetime
    n = 35
    start = datetime.datetime.now()
    def fib(n):
        return 1 if n < 2 else fib(n-1) + fib(n-2)
    for i in range(n):
        print(fib(i), end=' ')
    delta = (datetime.datetime.now() -start).total_seconds()
    print(delta)
    

    for循环:

    import datetime
    start = datetime.datetime.now()
    pre = 0
    cur = 1 # No1
    print(pre, cur, end=' ')
    n = 35
    for i in range(n-1):
        pre, cur = cur, pre + cur
        print(cur, end=' ')
    delta = (datetime.datetime.now() -start).total_seconds()
    print(delta)
    

    递归改进:

    pre = 0
    cur = 1 # No1
    print(pre, cur, end=' ')
    def fib(n, pre=0,cur=1): # recursion
        pre, cur = cur, pre + cur
        print(cur, end=' ')
        if n == 2:
          return
        fib(n-1, pre, cur)
    fib(n)
    

    #fib函数和循环的思想类似,参数n是边界条件,用n来计算;上一次的计算结果直接作为函数实参.和循环比较,性能相近;

    递归练习:

    求n的阶乘

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

    将一个数逆序放入列表中,例如123=>[4,3,2,1]

    def revert(x):
        if x == -1:
            return ''
        return data[x] + revert(x-1)
    
    print(revert(len(data)-1))
    
    
    def revert(n,lst=None):
        if lst is None:
            lst = []
    
        x,y = divmod(n,10)
        lst.append(y)
        if x == 0:
            return lst
        return  revert(x,lst)
    
    print(revert(12345))
    
    
    num = 123456
    def revert(num,target=[]):
        if num:
            target.append(num[len(num)-1]) #target.append(num[-1:])
            revert(num[:len(num)-1])
        return target
    
    print(revert(str(num)))
    

    猴子吃桃:猴子第一天摘下若干个桃子,当即吃了一半,不过瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃一个,以后每天早上都吃前一天剩下的一半零一个,第十天时,只剩下一个桃子,问第一天一共摘下多少个桃子

    假设猴子摘了x个桃子

    d1  x//2 -1

    d2  d1//2 -1

    d3  d2//2 -1

    ...

    d9  d8//2 -1

    d10 = 1

    def peach(days = 1):
        if days == 10:
            return 1
        return (peach(days+1)+1)*2
    print(peach())
    
    def peach(days = 10):
        if days == 1:
            return 1
        return (peach(days - 1)+1)*2
    
    print(peach())
    

    匿名函数:

    匿名函数即没有名字的函数,python借助lambda表达式构建匿名函数;

    格式:

    lambda  参数列表:  表达式

    lambda  x : x ** 2

    (lambda  x : x ** 2)(4)   #调用

    foo = lambda  x : x ** 2  #不推荐这么用

    匿名函数参数列表不需要小括号;冒号用来分割参数列表和表达式;不需要使用return,表达式的值,就是匿名函数的返回值;lambda表达式(匿名函数)只能写在一行上,被称为单行函数,主要用于高阶函数传参数,可以简化代码;

     print((lambda :0)())
     print((lambda x, y=3: x + y)(5))
     print((lambda x, y=3: x + y)(5, 6))
     print((lambda x, *, y=30: x + y)(5))
     print((lambda x, *, y=30: x + y)(5, y=10))
     print((lambda *args: (x for x in args))(*range(5)))
     print((lambda *args: [x+1 for x in args])(*range(5)))
     print((lambda *args: {x+2 for x in args})(*range(5)))
     [x for x in (lambda *args: map(lambda x: x+1, args))(*range(5))] # 高阶函数
     [x for x in (lambda *args: map(lambda x: (x+1,args), args))(*range(5))]
    
  • 相关阅读:
    http协议概述
    博客写起来一周年了~
    angular与vue的应用对比
    一些前端的小问题
    详解vue的数据binding原理
    闲的没事水一贴!
    关于angular1与angular2的应用区别
    angularjs优化方略
    rxjs学习笔记
    HTML5移动开发学习笔记
  • 原文地址:https://www.cnblogs.com/52py/p/7691840.html
Copyright © 2011-2022 走看看