1迭代器

         迭代器是访问集合元素的一种方式,迭代器对象从集合的第一个元素开始,直到所有的元素访问完成后结束,

         迭代器主要是用来和for循环进行配合,从而能用一种简单访问的接口来访问集合的元素,也是一种比较有性能的方法,因为在使用迭代器的时候,每次只返回一个元素,不像列表,每次需要在内存中加载所有的元素。

         可迭代的对象有序列类型stringlisttuple,非序列类型dictfile,还有就是自定义类型,当使用自定义类型的时候,必须实现__iter__()或者__getitem__()方法。

         迭代器是必须实现了__iter__()方法和next()方法,__iter__()方法返回迭代器自身,next()方法集合的下一个元素。

         迭代器一定是可迭代的,而可迭代的对象并不一定是迭代器,当将可迭代对象转换成迭代器的时候,可以使用iter()工厂函数,如下:

>>> myTuple = (123,'xyz',34.2) list是可迭代对象,内部实现了__iter__()方法

>>> i = iter(myTuple)将可迭代对象转换成迭代器,使用iter工厂函数

>>> type(i)i是一个迭代器对象

<type 'tupleiterator'>

>>> i.next() 迭代器具有next方法,返回下一个元素的值

123

>>> i.next()

'xyz'

>>> i.next()

34.2

>>> i.next()当所有元素都返回了时,会引发StopIteration异常

Traceback (most recent call last):

  File"<stdin>", line 1, in <module>

StopIteration

>>> k = myTuple.__iter__()也可以调用__iter__()函数返回一个迭代器

>>> type(k)

<type 'tupleiterator'>

         迭代器的限制,当使用迭代器的时候,不能向后移动,也不能回到开始,也不能复制一个迭代器,当要迭代同一个对象的时候,必须重新创建一个迭代器。

         在使用for循环的时候,会自动的将对象转换成一个迭代器,然后每次返回一个值,并且for能自动的捕捉到异常,然后退出循环。

>>> for i in myTuple:(使用for来迭代某个可迭代的对象)

...  print i

...

123

xyz

34.2

>>> iterTuple=iter(myTuple) for循环会得到一个迭代器对象

>>> while True: (进行循环,使用迭代器的next方法得到下一个值,并且自动捕捉异常,然后退出

...  try:

...  iterTuple.next()

...  exceptStopIteration:

...   break

...

123

'xyz'

34.2

>>>myDict={"name":"kel","age":28,"sex":"man"}遍历字典的时候,默认是遍历字典的keys返回一个列表,然后返回一个迭代器

>>> for i in myDict:

...  print i

...

age

name

sex

>>> myDict.keys().__iter__()字典类型的迭代器

<listiterator object at 0x7f535d589c90>

>>> type(i)

<type 'dictionary-keyiterator'>

>>> k=myDict.iterkeys()字典键的迭代器

>>> type(k)

<type 'dictionary-keyiterator'>

>>> k=myDict.itervalues()字典值的迭代器

>>> type(k)

<type 'dictionary-valueiterator'>

>>> k=myDict.iteritems()字典项的迭代器

>>> type(k)

<type 'dictionary-itemiterator'>

>>> f=file('kel.log')使用for循环读取文件的时候,默认是调用文件的readlines方法返回一个列表,然后返回一个迭代器

>>> for i in f:

...  printi.strip()

...

some

file

>>> i = f.__iter__()

>>> type(i)

<type 'file'>

>>> type(f)

<type 'file'>

>>> k=f.readlines().__iter__()文件类型的迭代器

>>> type(k)

<type 'listiterator'>


2列表解析

         列表解析主要是用来动态的生成一个新的列表,如下所示语法:

>>> l1 = [1,2,3,4]

>>> for i in l1:使用for循环来求列表l1偶数的平方

...  if i%2 ==0:

...  l2.append(i**2)

...

>>> l2

[4, 16]

>>> l2 = [i*2 for i in l1 if i%2 == 0]求列表l1偶数的平方

>>> l2

[4, 8]

         可以看出,当使用列表解析的时候,简单明了,再例如如下的例子:

>>> f = file('kel.log')统计文件中单词的个数

>>> count =0

>>> for eachline in f:使用双重循环来计算单词的个数

...  for wordin eachline.strip().split():

...   count +=1

...

>>> count

4

>>> f.seek(0)

>>> len([word for line in f for word inline.strip().split()])使用列表解析来计算单词的个数

4

>>> sum([len(word) for line in f for word inline.strip().split()])使用列表解析统计字母的个数

16

         列表解析支持嵌套的for循环。列表解析的不足就是一次性生成大量的数据,全部放入到内存中,那么可能对大量数据的迭代产生影响。


3生成器表达式

         生成器表达式是列表解析的一个扩展,生成器表达式和列表解析的语法基本相同,但是不同的是,生成器表达式返回的是一个生成器对象,而列表解析返回的是一个列表对象,如下所示:

>>> alist = [1,2,3,4]

>>> [a**2 for a in alist] 列表解析返回一个新的列表

[1, 4, 9, 16]

>>> (a**2 for a in alist)生成器表达式返回一个生成器对象

<generator object <genexpr> at0x7fa2beac0c80>

         生成器每次只产生一个数据,从而在使用内存上占有更大的优势,生成器产生的值是yield出来的,使用了延迟计算的方式,也就是在需要的时候才会返回这个值。

>>> f = open('kel.log')

>>> sum(len(word) for line in f for word inline.strip().split())使用生成器表达式,节省内存

16

>>> f.close()

>>> max(len(line.strip()) for line inopen('/var/log/messages') )使用生成器表达式一行代码统计最长的行长度