东方不败
迭代器和生成器是在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内置模块等。