天天看点

迭代器列表解析生成器

1、迭代器

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

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

         可迭代的对象有序列类型string,list,tuple,非序列类型dict,file,还有就是自定义类型,当使用自定义类型的时候,必须实现__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'

34.2

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

Traceback (most recent call last):

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

StopIteration

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

>>> type(k)

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

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

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

...  print i

...

xyz

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

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

...  try:

...  iterTuple.next()

...  exceptStopIteration:

...   break

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

>>> for i in myDict:

age

name

sex

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

<listiterator object at 0x7f535d589c90>

>>> type(i)

<type 'dictionary-keyiterator'>

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

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

<type 'dictionary-valueiterator'>

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

<type 'dictionary-itemiterator'>

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

>>> for i in f:

...  printi.strip()

some

file

>>> i = f.__iter__()

<type 'file'>

>>> type(f)

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

<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偶数的平方)

[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()])(使用列表解析来计算单词的个数)

>>> 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())(使用生成器表达式,节省内存)