您的位置:首页 > 编程语言 > Python开发

Python基础02--迭代器、生成器、列表解析

2017-09-15 14:14 686 查看
一、迭代器

    1.概述

(1) 迭代器是访问集合内元素的一种方式。

(2)迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。  迭代器不能回退,只能往前进行迭代。

(3)迭代器也不是线程安全的,在多线程环境中对可变集合使用迭代器是一个危险的操作。但如果小心谨慎,或者干脆贯彻函数式思想坚持使用不可变的集合,那这也不是什么大问题。  对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值,这是后话)。

(4)对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。  

(5)迭代器的另一个优点就是它不要求你事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。

(6) 迭代器更大的功劳是提供了一个统一的访问集合的接口。只要是实现了__iter__()方法的对象,就可以使用迭代器进行访问。

2.使用迭代器

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

   

test=[1,2,3,4]
test01=iter(test)
while True:
try:
print test01.next()
except:
pass
这里需要注意的是:iter()括号中内容必须要是可迭代对象,如list,tuple,set,dict等
test=set([1,2,3,4])
print(type(test))
test01=iter(test)
while True:
try:
print test01.next()
except:
pass
当迭代器访问完最后一个元素时,再访问下一个元素,就会因为元素不存在而抛出StopIteration异常.
(2)自己实现一个迭代器,如上所述,只需要在类的__iter__方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。但是需要自己实现迭代器的时候不多,即使需要,使用生成器会更轻松
(3)Python专门将关键字for用作了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作
(4)使用迭代器的循环可以避开索引,但有时候我们还是需要索引来进行一些操作的。这时候内建函数enumerate就派上用场咯,它能在iter函数的结果前加上索引,以元组返回
二、列表解析
列表解析(list comprehension)提供了一种优雅的生成列表的方法,能用一行代码代替十几行代码,而且不损失任何可读性。而且,性能还快很多很多
例如:
a=[]
for i in range(101):
if i%2==0:
a.append(i)


变成列表解析就是:

a=[x for x in range(101) if x%2==0]
实际上列表解析分成以下三部分:


x:我们需要的列表里面的结果(1st part) for x in range(101):
x来源——0~100的数字(2nd part) 
if x%2==0:x成立的条件,如果不成立就不放在列表里了(3rd part)
其他的一些例子:
(1)获取文本中所有单词的第1个字符
正常代码:
text="My house is full of flowers"
first_charts=[]
for word in text.split():
first_charts.append(word[0])
列表解析代码:

first_charts=[word[0] for word in text.split()]
三、生成器
生成器是一种迭代器,是一种特殊的函数,使用yield操作将函数构造成迭代器。普通的函数有一个入口,有一个返回值;当函数被调用时,从入口开始执行,结束时返回相应的返回值。
生成器定义的函数,有多个入口和多个返回值;对生成器执行next()操作,进行生成器的入口开始执行代码,yield操作向调用者返回一个值,并将函数挂起;挂起时,函数执行的环境和参数被保存下来;
对生成器执行另一个next()操作时,参数从挂起状态被重新调用,进入上次挂起的执行环境继续下面的操作,到下一个yield操作时重复上面的过程。Python的循环操作与C语言的实现不同,如果使用List等数据结构需要耗费大量的内容;
循环操作中使用生成器只需要在内存中实例化一个对象,可以减少内存占用,提高循环操作的执行速度。
举例:
def myG():
yield 1  //每一次调用返回一个值,并保存当前的执行环境
yield 2
yield 3
g=myG()   //g是一个生成器对象
while True:
try:
print next(g)
print next(g)
print next(g)
print next(g)
except:
pass
生成一个list:
>>>a=[7,8,9]
>>>b=[i**2 for i in a]  //方括号表示迭代器生成方式
>>>b
[49, 64, 81]
>>>ib=(i**2 for i in a)   //圆括号表示生成器生成方式
>>>ib
<generator object <genexpr> at 0x7f72291217e0>
>>>next(ib)
49
>>>next(ib)
64
>>>next(ib)
81
>>>next(ib)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

作者:catHeart
链接:http://www.jianshu.com/p/2ef36cdfd3b3
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。







                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: