Python 迭代器和生成器

Admin 2018-08-22 11:55:33 Python

在学习Python的数据结构时,列表/集合/字典推导式(list set dict comprehension)、可迭代对象(iterable)、迭代器(iterator)、生成器(generator)等,几个概念混杂不清,这篇文章将梳理下这几个概念。

可迭代对象(iterable)

在Python中,str、list、set、dict、file、socket数据类型都是可以被迭代,因此凡是可以返回一个迭代器的对象都可称为可迭代对象。

>>> x = [1, 2, 3]
>>> y = iter(x)
>>> z = iter(x)
>>> next(y)
1
>>> 
next(y)
2
>>> 
next(z)
1
>>> 
type(x)
<class 'list'
>>>> type(y)
<class 'list_iterator'>

这里x是一个可迭代对象,可迭代对象实现了__iter__方法,该方法返回一个迭代器对象

迭代器(iterator)

迭代器是一个可以记住遍历位置的对象,对象从集合的第一个元素开始访问,直到访问结束,只能往前不能回退。能在调用next()方法的时候返回下一个值,任何实现__iter__和__next__()方法的对象都是迭代器。

__iter__返回迭代器本身,__next__()返回下一个值,如果没有下一个值,则抛出StopIteration异常。因此迭代器就是实现了工厂模式的对象,在每次访问需要下一个值的时候都返回。

iter() 和 next()

int_list = [1,2,3,4]
new_list = iter(int_list) # 创建迭代器对象
print next(new_list)

迭代器对象可以使用for进行遍历

int_list = [1,2,3,4]
new_list = iter(int_list) # 创建迭代器对象
for x in new_list:
  print x

可以使用next()函数

import sys

int_list = [1,2,3,4]
new_list = iter(int_list) # 创建迭代器对象

while Ture:
  try:
    print next(new_list)
  except StopIteration:
    sys.exit()

生成无限序列:

>>> from itertools import count
>>> counter = count(start=13)
>>> next(counter)
13
>>> next(counter)
14

从一个有限序列生成无限序列:

>>> from itertools import cycle
>>> colors = cycle(['red', 'white', 'blue'])
>>> next(colors)
'red'
>>> next(colors)
'white'
>>> next(colors)
'blue'
>>> next(colors)
'red'

从一个无限序列生成有限序列:

>>> from itertools import islice
>>> colors = cycle(['red', 'white', 'blue'])  # infinite
>>> limited = islice(colors, 0, 4)            # finite
>>> for x in limited:                         
...    print(x)
red
white
blue
red

直观的感受一个迭代器:

class Fib:
    def __init__(self):
        self.prev = 0
        self.curr = 1

    def __iter__(self):
        return self

    def __next__(self):
        value = self.curr
        self.curr += self.prev
        self.prev = value
        return value>>> 
f = Fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Fib是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(实现了__next__方法).

生成器(generator)

生成器在Python中是最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过生成器更加的优雅,它不需要__iter__()和__next__()方法,只要使用了yield的函数就被称为生成器(generator),跟普通函数不同的是,生成器返回的是一个迭代器,只能用于迭代操作(可以理解生成器就是一个迭代器),在调用的过程中,当遇到yield时函数会暂停并保存当前所有运行的状态,返回yield的值,并在下一次next()方法时从当前位置继续执行。

def Fibonacci(num):
    a, b = 0,1
    while num > 0:
       yield b
       a ,b = b, a+b
       num -= 1

for i in Fibonacci(10):
     print i

生成器表达式(generator expression)

>>> a = (x*x for x in range(10))
>>> a
<generator object <genexpr> at 0x401f08
>>>> sum(a)
285

总结

  • 可迭代对象实现__iter__方法,该方法返回一个迭代器对象

  • 迭代器有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__()和__iter__()方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果

  • 生成器是一种特殊的迭代器,他返回值不是通过return而是yield

参考文档: https://docs.python.org/2/library/stdtypes.html#iterator-types

相关文章
最新推荐