python 生成器与迭代器(yield 用法)
背景
首先,我不会解释这两个名词,我看过很多遍解释,可还是看不懂,还是直接看使用情景吧。
我们以佩波拉契数列为例,当我们不知道迭代器的情况下,我们写出来的代码可能是这样子的:
'''这种方式计算fib(100)都很吃力'''
fib = lambda n:fib(n-2) + fib(n-1) if n>1 else 1
或者优化一下,变成这样子:
'''
将迭代结果存入temp中,避免重复的计算,
这样可以提高计算速度,但是当计算fib(4000)时,会报:
“maximum recursion depth exceeded in comparison”
也就是说会超过最大迭代次数
'''
temp = {}
def fib(n):
if n in temp:
return temp[n]
if n>1:
_t = fib(n-1) + fib(n-2)
temp[n] = t
return _t
else:
return 1
考虑到进一步的优化,我们就需要引进python的yield 语法
使用yield
yield的用法简单来说就 返回yield运行结果,当调用__next__时,再次运行至yield处,并返回 。所以我们可以利用这一特点,让fib函数每次只返回当前和前一个的值,再次运行时更新这两值, 并返回就好了。于是有了下面的代码:
'''
这次我们可以最大程度发挥计算机性能,
比上个版本能计算的更多也更快(我电脑能计算6位数的fib值)
'''
def fib_gen():
'''
这时一个佩波拉契数列的生成器,每次迭代返回当前值和前一个的值
'''
c , p = 1,1
while True:
yield p # 每次next运行到此,并返回p的值。当再次调用时,继续执行下面代码,
p, c = c, c+p # 计算下次p的值
def fib(n):
'''根据情况不断运行next(f),直到适合的条件'''
f = fib_gen()
for i in range(n+1):
cur = next(f)
return n
我们在看一个简单的生成器的例子
In [1]: array = [1,2,3,4]
In [2]: f = (i for i in array) # 是不是看起来很像“元组推倒式”,其实这是一个生成器。python并没有元组的推倒式
In [3]: f # 不信,我们来实际看看
Out[3]: <generator object <genexpr> at 0x10882df10>
In [4]: [i for i in f] # 生成器是可以迭代的,所以列表推到能取出值
Out[4]: [1, 2, 3, 4]
In [5]: [i for i in f]
Out[5]: [] # 此时,f中的数据全部取出,调用next(f) 取不出来值了
总结
- 从这个例子中我们可以发现,当使用yield后,函数并不是立刻执行,而是调用next的时候,我们才取出值,没调用的时候,它只是一个生成器。相当于保存了上次运行的现场。
- 当调用next时,没有找到yield返回时,便会终止,并报StopIteration错误, 本例子中是死循环,不会发生这种情况。感兴趣的可以把
while True改成while p < 100之类的试试
python 生成器与迭代器(yield 用法)的更多相关文章
- Python 生成器与迭代器 yield 案例分析
前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...
- python 生成器和迭代器
迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退) 2.可迭代对象:实现了 ...
- python 生成器和迭代器有这篇就够了
本节主要记录一下列表生成式,生成器和迭代器的知识点 列表生成器 首先举个例子 现在有个需求,看列表 [0,1,2,3,4,5,6,7,8,9],要求你把列表里面的每个值加1,你怎么实现呢? 方法一(简 ...
- Python生成器,迭代器,可迭代对象
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...
- 【转】python 生成器和迭代器有这篇就够了
总结得特别好,转自:https://www.cnblogs.com/wj-1314/p/8490822.html 本节主要记录一下列表生成式,生成器和迭代器的知识点 列表生成器 首先举个例子 现在有个 ...
- Python 生成器 (generator) & 迭代器 (iterator)
python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...
- python 生成器,迭代器,闭包,装饰器
1.生成器,迭代器,闭包,装饰器的优点 生成器就是一类特殊的迭代器 迭代器的优点也即生成器的优点: 1.节约内存.python在使用生成器时对延迟操作提供了支持. 2.迭代到下一次的调用时,所使用的参 ...
- 每日一问:Python生成器和迭代器,with上下文管理工具
1.生成器: 1.1 起源: 如果列表中有一万个元素,我们只想要访问前面几个元素,对其进行相关操作,通过for循环方式效率太低,并且后面的元素会浪费内存,还会受到内存限制,所以产生生成器来解决这个问题 ...
- Python基础之函数:6、异常相关和生成器对象、yield用法、生成器表达式
目录 一.异常常见类型 1.类型错误 2.缩进错误 3.索引错误 4.语法错误 5.属性错误 6.key键错误 二.异常处理语法结构 1.基本语法结构 2.查看错误类型 3.针对不同类型所作措施 4. ...
随机推荐
- python set_index与reset_index的妙用
- 性能测试工具LoadRunner31-LR之链接mysql
步骤: 1.建好mysql数据库并启动 2.下载libmysql.dll,放到保存脚本的文件夹下 3.编写脚本并运行 Action() { int rc; //定义状态变量,0表示成功,非0表示失败 ...
- HDU 4185 ——Oil Skimming——————【最大匹配、方格的奇偶性建图】
Oil Skimming Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- netty之==TCP粘包/拆包问题解决之道(一)
一.TCP粘包/拆包是什么 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在 ...
- 深入理解vertical-align和line-height的关系
vertical-align的百分比值不是相对于字体大小或者其他什么属性计算的,而是相对于line-height计算的.举个简单的例子,如下CSS代码: { line-height: 30px; ve ...
- GPU学习随笔
NVML NVAPI GDK GDK包含NVML NVAPI库不能提供获取GPU使用率的接口 NVML能提供但不支持geforce系列 NVAPI.dll NVAPI64.dll动态加载可以查 ...
- (转)GitHub上整理的一些工具,求补充 -
SegmentFault 技术站点 Hacker News:非常棒的针对编程的链接聚合网站 Programming reddit:同上 MSDN:微软相关的官方技术集中地,主要是文档类 infoq ...
- 修复kindEditor点击加粗, 内容焦点跳动的问题
大概1560~1569行 pos : function() { var self = this, node = self[0], x = 0, y = 0; if (node) { if (node. ...
- vue-router配置
首先在App.vue中 1.使用router-link组件来导航,通过‘to'属性指定链接,<router-link> 默认会被渲染成一个 `<a>` 标签 <route ...
- Android setUserVisibleHint-- fragment真正的onResume和onPause方法
这个情况仅适合与多个fragment之间切换时统计,而非activity和fragment同时交互,因当时项目为首页4个fargment时长统计,因此适合,经下面网友评论指出,特在这里写出此问题,因最 ...