博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 迭代器(iterator)
阅读量:4169 次
发布时间:2019-05-26

本文共 2714 字,大约阅读时间需要 9 分钟。

1》

迭代器是一个实现了迭代器协议的对象。Python中的迭代器协议就是具有next方法的对象会前进到下一结果,而在一系列结果的末尾则会引发StopIteration异常。任何这种类型的对象在Python中都可以用for循环或其他遍历工具进行迭代,迭代工具内部会在每次迭代时调用next方法,并且通过捕捉StopIteration异常来结束迭代。使用迭代器一个显而易见的好处就是:迭代器提供了一个统一的访问序列的接口,只要是实现了__iter__()方法的对象,就可以使用迭代器通过调用next()方法每次只从对象中读取一条数据,不会造成内存的过大开销。

比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:

f=open(r'C:\Users\Administrator\Desktop\wahaha.txt','r')
for line in f.readlines():
    print line[:-1] #去掉每行末尾的换行符
运行结果:
love python
love python2
love python3
这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。

利用file的迭代器,我们可以这样写:

f=open(r'C:\Users\Administrator\Desktop\wahaha.txt','r')
for line in f: #使用文件迭代器
    print line[:-1] #去掉每行末尾的换行符
运行结果:
love python
love python2
love python3
这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。这就是迭代器的一个显著的优点,它不要求我们事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得迭代器特别适合用于遍历一些巨大的或是无限的序列,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)

2》

对于支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。迭代器不能回退,只能往前进行迭代。迭代器不是线程安全的,在多线程环境中对可变集合使用迭代器是一个危险的操作(保守的方法是坚持使用不可变的集合)。

使用内建的工厂函数iter(iterable)可以获取迭代器对象:

>>> l
[0, 1, 2, 3, 4]
>>> it=iter(l)
>>> it
<listiterator object at 0x069F6C50>
使用迭代器的next()方法可以访问下一个元素:
>>> it.next()
0
>>> it.next()
1
>>> it.next()
2
如果是Python 2.6+,还有内建函数next(iterator)可以完成这一功能:
>>> next(it)
3
>>> next(it)
4

如何判断迭代器是否有更多的元素可以访问呢?如果我们已经访问到了最后一个元素,再使用next()方法会怎样呢?

>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Python遇到这样的情况时将会抛出StopIteration异常。事实上,Python正是根据是否检查到这个异常来决定是否停止迭代的。 

了解了这些情况以后,我们就能使用迭代器进行遍历了。

>>> l
[0, 1, 2, 3, 4]
>>> it=iter(l)
>>> try:
...     while True:
...         item=it.next()
...         print item
... except StopIteration:
...      pass
... 
0
1
2
3
4

实际上,因为迭代操作如此普遍,Python专门将关键字for用作了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。上述代码可以写成如下我们非常熟悉的形式:

>>> l
[0, 1, 2, 3, 4]
>>> for item in l:
...     print item,
... 
0 1 2 3 4
首先Python将对关键字in后的对象调用iter函数获取迭代器,然后调用迭代器的next方法获取元素,直到抛出StopIteration异常。对迭代器调用iter函数时将返回迭代器自身,所以迭代器也可以用于for语句中,不需要特殊处理。

>>> l

[2, 3, 4]
>>> it=iter(l)
>>> it
<listiterator object at 0x030B5E50>
>>> itt=iter(it)
>>> itt
<listiterator object at 0x030B5E50>

3》

常用的几个内建数据结构tuple、list、set、dict都支持迭代器,字符串也可以使用迭代操作。我们可以自己实现一个迭代器,只需要在类的__iter__方法中返回一个对象,这个对象需要拥有一个next()方法,这个方法能在恰当的时候能够抛出StopIteration异常即可。并不是必须要抛出异常,不抛出异常的迭代器将进行无限迭代,某些情况下这样的迭代器很有用,此时,我们需要自己判断元素并中止,否则就死循环了!

使用迭代器的循环可以避开索引,但有时候我们还是需要索引来进行一些操作的。这时候内建函数enumerate就派上用场咯,它能在iter函数的结果前加上索引,以元组返回,用起来就像这样:

>>> l
[3, 4, 5, 6]
>>> for i,v in enumerate(l):
...     print i,v
... 
0 3
1 4
2 5
3 6

友情链接:

关于iter( )函数的使用,参考:

关于enumerate( )函数的使用,参考:

转载地址:http://tdyai.baihongyu.com/

你可能感兴趣的文章
整理网络安全措施的5个小技巧
查看>>
原来Java反序列化远程执行漏洞这么简单
查看>>
移动应用安全基础篇——解密iOS加密数据
查看>>
针对国内IP发起攻击的DDoS样本分析
查看>>
入侵win10(下)--渗透系统
查看>>
Linux主机安全检查与应急响应
查看>>
关于Metasploit 5中测试模块的移植与验证
查看>>
GoMet:Go编写的多平台Agent和控制器
查看>>
CVE-2019-11815:Linux kernel漏洞
查看>>
剥丝抽茧,层层破解!看我如何一步步绕过防火墙直至获取你的支付卡信息
查看>>
CVE-2019-0708漏洞: RDP= Really DO Patch?
查看>>
使用新型反检测技术:与MuddyWater相关的BlackWater恶意活动分析
查看>>
使用ee-outliers和Elasticsearch检测可疑子进程
查看>>
Office 365出现网络钓鱼,用户需多加注意
查看>>
MalConfScan:从已知的恶意软件家族中提取配置信息
查看>>
不死的EternalBlue(永恒之蓝)
查看>>
针对中亚地区政府部门的攻击:通过Office漏洞传播新型Hawkball后门
查看>>
Windows 10安全指南
查看>>
<<OCM实验选讲>> 第七课 Oracle数据库管理实验
查看>>
<<OCM实验选讲>> 第八课 Oracle性能优化实验
查看>>