专否 写文章

东方不败

Oct 17, 2018
Follow

python的迭代器(Iterator)和生成器(Generate)

迭代器和生成器是在python2.2引入的,它们事实上是在鼓励一种低耦合度的编程方式。那什么是迭代器与生成器呢?写到这,说个实话,我对它们其实也是半懂不懂。

在《python cookbook》中是这么形象地描述迭代器——迭代器协议他妈的就是由两部分组成,前者是生产者,后者是消费者。生产者说:“我知道怎么提供数据,我负责的就是准备好提供的数据,然后每次提供一个”;消费者说,“爷就是吃货,请生产者每次提供一个数据给我吃,如果你的数据给我吃光了,要跟我说你没有数据了。”

说得再多,不如先举一个简单的例子。

#coding=utf-8
def func():
    yield 33
    yield 32
    yield 22
    yield 101
 
a = func()
print a
print a.next() #会输出33
print a.next() #会输出32
print a.next() #会输出22
print a.next() #会输出101
print a.next() #没有东西可输出了,所以就报错StopIteration

输出的结果是

>>> <generator object func at 0x10a647460>
>>> 33
>>> 32
>>> 22
>>> 101
>>> Traceback (most recent call last):
  File "zhuangshiqi.py", line 14, in <module>
    print a.next() #没有东西可输出了,所以就报错了
StopIteration



上面这个简单的例子就涵盖了迭代器与生成器。迭代器是一个对象,上面的a变量就是一个具体的对象;而生成器是构造迭代器的函数,指的就是上面的func()函数。

上面这句话很简单,但是万变不离其宗,只是融入很多其他的知识点,看起来有些不同而已。

再举一个例子:

>>> list = range(4)
>>> it = iter(list) ###iter()
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


上面代码的第二行iter()是python的一个内置函数,当传入一个列表后,然后这个函数就根据这个列表构建一个迭代器对象,也就是省去每次自己写生成器函数了。(此外,当传入的不是列表而是一个字符串时,字符串将被自动转化成等价于每个字母组成的列表,比如当你传入'abcd'时,就等价于传入[ 'a', 'b', 'c', 'd' ]了…)

另外,next(it)等价于it.next()



再看一个例子:

#coding=utf-8
def func(n):
    for i in range(n):
        yield i
 
print 'func(4) results:'
for i in func(4):
    print i
 
print 'range(4) results:'
for i in range(4):
    print ish

输出的结果是:

>>> func(4) results:
>>> 0
>>> 1
>>> 2
>>> 3
>>> range(4) results:
>>> 0
>>> 1
>>> 2
>>> 3

这里我唯一要做的就是解释一下for i in range(4)的原理——range(4)生成的是一个列表,即[ 0, 1, 2, 3 ] ;而正常情况下我们for i in <"list">实则是for 暗地里把这个list转化为了一个迭代器对象,就好比for在暗地里用了一下iter()函数。所以说上述直接用for i in func(4)也是等效的。




今天吃饭了,改日对再进行补充,还要说迭代器的特殊用法、enumerate函数、map函数、filter函数、生成器表达式、列表解析以及itertools内置模块等。


喜欢这个文章 | 分享 | 新建跟帖