Python 中容易混淆的概念--迭代器与生成器
迭代器与生成器
迭代器(iterator)与生成器(generator)是 Python 中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例子。
for 语句与可迭代对象(iterable object):
for i in [1, 2, 3]:
print(i)
obj = {"a": 123, "b": 456}
for k in obj:
print(k)
这些可以用在 for 语句进行循环的对象就是可迭代对象。除了内置的数据类型(列表、元组、字符串、字典等)可以通过 for 语句进行迭代,我们也可以自己创建一个容器,包含一系列元素,可以通过 for 语句依次循环取出每一个元素,这种容器就是迭代器(iterator)。
for循环可以用于python中任何序列类型,包括序列、元组以及字符串。例如:
>>> for x in [1,2,3,4]: print(x * 2,end='')
...
2468
>>> for x in (1,2,3,4): print(x * 2,end='')
...
2468
>>> for y in 'python': print(y * 2 ,end=' ')
...
pp yy tt hh oo nn
实际上,for循环甚至比这更为通用:可用于任何可迭代对象。可以认为for是一种迭代工具,还有一些例如:列表解析、in成员关系测试以及map内置函数等。
文件迭代器
文件有一个方法,名为__next__,每次调用时,就会返回文件中的下一行。值得注意得是,到达文件末尾时,__next__会引发内置的StopIteration异常,而不是返回空字符串。
例如:
注意,这里的print使用end=''来一直添加一个\n,因为行字符串已经有一个(如果没有这点,我们的输出将变成两行隔开)、
这样读取文件的好处有三点:
1.写法简单
2.运行速度快
3.从内存使用的情况来说也是最好的
相同效果的原始方式,是以for循环调用文件的readlines方法,是将文件加载到内存,做成行字符串的列表。
虽然两种效果相同,但是后者是将文件一次性加载到内存,如果文件太大,计算机内存空间不够,甚至不能工作。前者迭代器版,对于这种问题就有了免疫功能。(python3通过重写i/o以支持unicode文本从而使的这一有点不明显,并更少依赖于系统)
当然也可以用while循环来实现,但是相对来说while还是比for慢。
手动迭代:iter和next
为了支持手动迭代代码,python3中还提供一个内置函数next,他会自动掉用一个对象的__next__方法。给定一个可迭代对象z,调用next(z)等同于z.__next__(),但是前者简单很多。例如:
从技术的技术的角度将,当for循环开始时,会通过它给iter内置函数,一便从可迭代对象获得一个迭代器,返回的对象含有需要的next方法。
列表以及很多其他的内置对象,不是自身的迭代器,因为他们支持多次打开迭代器。对这样的对象,我们必须调用iter来启动迭代:
从技术上讲,for循环调用内部等价的I.__next__,而不是这里使用的next(I)
现在我们展示一下自动和手动迭代之间的对等性:
关于try语句运行一个动作并且捕获运行过程中发生的异常,我将在后续发表文章,详细解说。
以上就是Python 中容易混淆的概念--迭代器与生成器的详细内容,更多请关注其它相关文章!