1、理解函数执行流程

  1. def foo1(b, b1=3):
  2. print("foo1 called", b, b1)
  3. def foo2(c):
  4. foo3(c)
  5. print("foo2 called", c)
  6. def foo3(d):
  7. print("foo3 called", d)
  8. def main():
  9. print("main called")
  10. foo1(100, 101)
  11. foo2(200)
  12. print("main ending")
  13. main()

执行结果

  1. main called
  2. foo1 called 100 101
  3. foo3 called 200
  4. foo2 called 200
  5. main ending

  • 全局帧中生成foo1、foo2、foo3、main函数对象
  • 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函数返回

2、递归Recursion

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

斐波那契数列案例

  1. 斐波那契数列Fibonacci number:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
    如果设F(n)为该数列的第n项(nN*),那么这句话可以写成如下形式::F(n)=F(n-1)+F(n-2)
    F(0)=0F(1)=1, F(n)=F(n-1)+F(n-2)

for循环写法:

  1. per = 0
  2. cut = 1
  3. print(cut)
  4. for a in range(5):
  5. per,cut = cut,cut + per
  6. print(cut)

递归写法:

  1. def fib(n):
  2. return 1 if n < 2 else fib(n-1) + fib(n-2)
  3.  
  4. for a in range(5):
  5. print(fib(a),end=" ")

解析:

fib(3) + fib(2)

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

fib(2) 调用 fib(2)、fib(1)

fib(1) 边界

递归要求:

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

递归性能

  1. #循环写法
  2. import datetime
  3. start = datetime.datetime.now()
  4. per = 0
  5. cut = 1
  6. print(cut,end=" ")
  7. n = 35
  8. for a in range(n-1):
  9. per,cut = cut,cut + per
  10. print(cut,end=" ")
  11. delta = (datetime.datetime.now() - start).total_seconds()
  12. print(delta)
  13. #执行结果
  14. 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 0.000796
  15. #递归写法
  16. import datetime
  17. n = 35
  18. start = datetime.datetime.now()
  19. def fib(n):
  20. return 1 if n < 2 else fib(n-1)+fib(n-2)
  21.  
  22. for a in range(n):
  23. print(fib(a),end=" ")
  24. delta = (datetime.datetime.now() - start).total_seconds()
  25. print(delta)
  26. #执行结果
  27. 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 7.415541
  • 循环稍微复杂一些,但是只要不是死循环,可以多次迭代直至算出结果
  • fib函数代码极简易懂,但是只能获取到最外层的函数调用,内部递归结果都是中间结果,而且给定一个n都要进行近2n次递归,深度越深,效率越低。为了获取斐波那切数列需要外面在套一个n次循环,效率更低了。
  • 递归还有深度限制,如果递归复杂,函数反复压栈,栈内存很快就溢出了

递归写法改进

  1. def fib(n,pre=0,cut=1):
  2. pre, cut = cut, cut + pre
  3. if n == 0 :
  4. return pre
  5. return fib(n-1,pre,cut)
  6. print(fib(5))
  • fib函数和循环的思想类似
  • 参数n是边界条件,用n来计算
  • 上一次的计算结果直接作为函数的实参
  • 效率高
  • 和循环比较,性能相近,所以并不是说递归一定效率低下,但是递归有深度限制

间接递归

  1. def foo1():
  2. foo2()
  3. def foo2():
  4. foo1()
  5. foo1()

间接递归,是通过别的函数调用了函数自身

但是,如果构成了循环递归调用是非常危险的,但是往往这种情况在代码复杂的情况下,还是可能发生这种调用的,要用代码的规范来规避这种递归调用的发生

递归总结

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

3、匿名函数

  • 匿名,既没有名字
  • 匿名函数,既没有名字的函数
    • 没有名字如何定义
    • 没有名字如何调用
    • 如果能调用,如果使用

python借助lambda表达式构建匿名函数

格式:

  • lambda参数列表:表达式
  • lambda x : x **2
  • (lambda x : x **2)(4) #调用
  • foo = lamdba x,y :(x+y)**2 #不推荐这样用  建议使用普通函数

说明:

  • 使用lambda 关键字来定义匿名函数
  • 参数列表不需要小括号
  • 冒号是用来分割蚕食列表和表达式的
  • 不需要使用return,表达式的值,就是匿名函数返回值
  • lambda表达式(匿名函数) 只能写在一行上,被称为单行函数
  1. print((lambda :0)())
  2. print((lambda x,y=3: x + y )(5))
  3. print((lambda x,y=3: x + y )(5,5))
  4. print((lambda x, *, y=30: x + y)(5))
  5. print((lambda x, *, y=30: x + y)(5, y=10))
  6. print((lambda *args: (x for x in args))(*range(5)))
  7. print((lambda *args: [x+1 for x in args])(*range(5)))
  8. print((lambda *args: {x+2 for x in args})(*range(5)))
  9.  
  10. [x for x in (lambda *args: map(lambda x: x+1, args))(*range(5))]
  11. [x for x in (lambda *args: map(lambda x: (x+1,args), args))(*range(5))]

python 递归和匿名函数的更多相关文章

  1. Python 递归、匿名函数、map和filter day4

    一.递归---函数自己调用自己 1.一个错误递归的例子: count=0 def hello(): global count count+=1 print("count %s"%c ...

  2. python 递归、匿名函数、

    1.递归:就是函数自己调用自己.(注:递归最多循环999) 2.匿名函数(意义:减少内存占用) lambada 定义一个匿名函数,eg:lambad x,b:x+b  (:前面是入参eg:x,b,:后 ...

  3. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  4. python之三元表达式、列表推导、生成器表达式、递归、匿名函数、内置函数

    目录 一 三元表达式 二 列表推到 三 生成器表达式 四 递归 五 匿名函数 六 内置函数 一.三元表达式 def max(x,y): return x if x>y else y print( ...

  5. python 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    http://www.cnblogs.com/linhaifeng/articles/7580830.html 三元表达式.列表推导式.生成器表达式.递归.匿名函数.内置函数

  6. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

  7. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  8. Python入门篇-匿名函数

    Python入门篇-匿名函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.匿名函数概述 1>.什么是匿名函数 匿名,即没有名字 匿名函数,即没有名字的函数 2>. ...

  9. python全栈开发-Day12 三元表达式、函数递归、匿名函数、内置函数

    一. 三元表达式 一 .三元表达式 仅应用于: 1.条件成立返回,一个值 2.条件不成立返回 ,一个值 def max2(x,y): #普通函数定义 if x > y: return x els ...

随机推荐

  1. 阿里云轻量级服务器和NGINX部署Django项目

    部署条件: 1.一台阿里云服务器(本人的是CentOS系统的服务器) 2.已经构建好的项目 3.服务器上安装并配置Nginx 首先第一步:在服务器上安装并配置Nginx 进入服务器 $ ssh roo ...

  2. [ Educational Codeforces Round 65 (Rated for Div. 2)][二分]

    https://codeforc.es/contest/1167/problem/E E. Range Deleting time limit per test 2 seconds memory li ...

  3. vue 安装 ‘node-sass’ 运行报错:ERROR in Cannot find module 'node-sass'

    好像是由于cnpm安装导致.执行下面的安装代码,或者使用npm 安装node-sass cnpm install node-sass@latest

  4. OTFS Research Notes

    △f = f·v·cosθ/c,f表示载波频率,5G/B5G朝着毫米波等高频段方向发展,因此多普勒拓展的影响将更显著.此外,Masssive MIMO的现有规模已达256维度,并将朝着上千的规模发展. ...

  5. 学到了林海峰,武沛齐讲的Day16完

    函数嵌套 foo()()() ====  foo()>>>gxr   gxr()>>>wsb    wsb()>>执行wsb函数 lambda   一行 ...

  6. Greenplum 调优--VACUUM系统表

    Greenplum 调优--VACUUM系统表 1.VACUUM系统表原因 Greenplum是基于MVCC版本控制的,所有的delete并没有删除数据,而是将这一行数据标记为删除, 而且update ...

  7. MySQL 事务 MVCC 版本链

      版本链   对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL唯一键时都不会包含row_id列):  1) ...

  8. Chrome安装.crx文件

    解决"只能通过Chrome网上应用商店安装该程序"的方法 http://chromecj.com/utilities/2015-04/423.html 1.更多工具->扩展程 ...

  9. nowcoder 181045 / 克洛涅的多项式 构造+思维

    题意:有多项式 $F(x),G(x)$,最高次项分别为 $n,m$.$F(x)$ 最高次项系数为 $1$. $m<n$ 给定 $n$ 个不同的点值,满足 $F(x[i])=G(x[i])$ 给定 ...

  10. linux系列(十六):which命令

    1.命令格式: which 可执行文件名称 2.命令功能: which指令会在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果. 3.命令参数: -n 指定文件名长度,指定的长 ...