
Day6 递归函数
发布日期:2021-05-20 18:23:14
浏览次数:16
分类:博客文章
本文共 1212 字,大约阅读时间需要 4 分钟。
##递归函数看的云里雾里,廖雪峰大师给出的练习题我也没搞懂,先mark下理解的,其他的后续再说……
通过之前的学习已经知道,函数的内部是可以调用其他函数的,如果一个函数在内部调用自身本身,那么这个函数就是递归函数。
定义一个计算阶乘n!的函数 n!= 1x2x3x4x……xn,用函数来表示可以看出 jx(n)= n! = 1 x 2 x 3 x ... x (n-1) x n = (n - 1)! x n = jx(n-1) x n 所以jx(n)可以表示为 jx(n-1) x n ,但是当n=1时,就不行了。因此需要额外处理一下n = 1 的情况。于是 阶乘用递归方式写出来就是: def jx(n): if n == 1: return 1 return n * jx(n - 1) 递归函数定义简单,逻辑清晰,理论上所有的递归函数都可以写成循环的方式,但是循环的逻辑不如递归清晰。
栈溢出 使用递归函数需要注意防止栈溢出, 函数调用是通过栈stack这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以当递归调用的次数过多时,就会导致栈溢出。
jx(1000) RecursionError: maximum recursion depth exceeded in comparison 尾递归优化 解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。 尾递归是指在函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样编译器或者解释器就可以把尾递归做优化,使递归无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。 例: 在前面的例子里,由于 return n * jx(n - 1) 引用了乘法表达式,所以就不是尾递归。要使用尾递归方式没主要是要把每一步的乘积传入到递归函数中。 def jx(n): return jx_iter(n, 1) def jx_iter(num,r1): if num == 1: return r1 return jx_iter(num - 1, num * r1) #返回本次计算结果给函数本身,进入下一轮循环。 尾递归调用时如果做了优化,栈不会增长,因此无论多少次调用也不会导致栈溢出。但是说这么多,在试验上面这个尾递归优化的例子时,发现python3依然会报错,因为……Python解释器也没做尾递归优化。 递归函数小结: 1. 使用递归函数的优点时逻辑简单清晰,缺点是过深的调用会导致栈溢出。 2. 针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的变成语言只能通过尾递归实现循环。 3. python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年04月17日 19时21分35秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
在 eclipse 中将 web 项目部署到 tomcat 服务器上
2019-03-22
iOS关于申请公司开发者账号缴费支付
2019-03-22
10-3 A1-4在产品表中找出库存数量大于50的产品的信息 (20 分)
2019-03-22
Ajax学习笔记-错误的处理-7
2019-03-23
SparkStreaming利用队列生成测试数据源
2019-03-23
js——BOM操作知多少?
2019-03-23
划分子网与NAT的区别。。。
2019-03-23
钻石操作符使用升级
2019-03-23
设置方法区大小与OOM
2019-03-23
Laravel 直接返回404页面
2019-03-24
记一次内部系统渗透测试:小漏洞组合拳
2019-03-24
常用元素操作的方法
2019-03-24
命名实体识别数据预处理
2019-03-25
解决 matplotlib 中文显示乱码的问题
2023-01-23
解决打开 json 文件中文乱码的问题
2023-01-23
计算机网络基础:DHCP服务的部署
2023-01-23
计算机网络基础:NAT 网络地址转换
2023-01-23
计算机网络基础:PKI(公钥基础设施)
2023-01-23
计算机网络基础:VLAN(虚拟局域网)
2023-01-23
计算机网络基础:文件共享服务器(注册表更改)
2023-01-23