所谓的 iterator 指实现了 next 方法的对象,这种对象可以使用 for dumb in iter 的方式进行遍历。习惯上对一个对象使用 iter() 方法等价于调用其 __iter__ 方法获得对应的 iterator,而后调用该 iterator 的 next 方法遍历。通常一个 iterator 实现的 __iter__ 方法返回自己。
下面看看 itertools 的 count 方法:
>>> import itertools >>> c = itertools.count() >>> type(c) <type 'itertools.count'> >>> dir(c) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'next'] >>> for i in c: ... print i ... if i > 10: ... break ... 0 1 2 3 4 5 6 7 8 9 10 11
下面将介绍 itertools 里面其他的一些创建 iterator 的函数。一类和 count 类似,返回的是可以无限迭代下去的:
- count 返回给定初始值和 step 向后计数的 iterator;
- cycle 给出循环 iterator;
- repeat 给出重复某个值的 iterator;
- chain 给出遍历每个参数的每个 iterator 的 iterator
- compress 有两个参数 a 和 b,返回 a[i] if b[i]
- dropwhile 两个参数,前面一个条件(functor),后面是遍历的序列,返回去掉序列前面不符合条件的序列的 iterator;
- groupby 返回的是对 key/data 遍历的 iterator,需要提供 keyfunction 这是前面通过 sort 排序使用的,然后 groupby 就会返回一个 tuple,第一个是 key,第二个是 key 相同的元素列表;
- ifilter/ifilter_false 和 filter 类似,只是返回的是 iterator 而不是 list;
- islice 返回类似 slice 操作的 iterator;
- imap 返回类似 map 操作的 iterator;
- startmap 和 imap 不同的是,imap 是每个参数一个 list,startmap 是每一组参数一个;
- tee 可以将一个 iterator 变成 n 个独立的 iterator,这样某些问题里面可以分开到多线程里面处理; tee 过的 iterator 最好不要用在别处;
- takewhile 和 dropwhile 类似,但是仅仅取条件成功的元素;
- izip 和 zip 类似的 iterator;izip_longest 允许设置 fillvalue 用于补齐;
- product 用于产生 Decartes 积;
- permutations 用于产生置换;
- combinations 产生组合;combination_with_replacement 带重复的组合;
需要说明的是 python 比较奇怪的产生 iterator 的方式是返回使用 yield 关键字,这种对象/函数一般称为 generator,利用 generator 可以很容易写出 iterator,而不打扰遍历的逻辑。比如文档中给出的 chain 函数的等价写法
def chain(*iterables):
# chain(’ABC’, ’DEF’) --> A B C D E F
for it in iterables:
for element in it:
yield element逻辑上我们就是这样遍历 chain 的所有参数,但是如果要写成一个 iterator 会比较麻烦,需要记录遍历到哪个参数了,它的 iteraotor 是谁,iteration 结束后跳到下一个参数;而 yield 的写法就很直观。另外 iteration 结束 iterator 需要 raise StopIteration 的异常;如果使用 yield 则没有必要手工写这个异常。
No comments:
Post a Comment