Python常用模块之三 itertools
itertools模块为python2.6之后引入的,包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,
此模块中的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器(如生成器和生成器表达式)的函数联合使用。
注意itertools模块中的函数所创建的都是对象,并且是可迭代对象。
1、itertools.count(start=0, step=1)
创建一个迭代器,生成从n开始的连续整数,如果忽略n,则从0开始计算(注意:此迭代器不支持长整数)
如果超出了sys.maxint,计数器将溢出并继续从-sys.maxint-1开始计算
In [34]: a = itertools.count(10)
In [35]: a
Out[35]: count(10)
In [36]: print a
count(10)
In [37]: a.next()
Out[37]: 10
In [38]: a.next()
Out[38]: 11
In [39]: a.next()
Out[39]: 12
2、itertools.cycle(iterable)
创建一个迭代器,对iterable中的元素反复执行循环操作,内部会生成iterable中的元素的一个副本,此副本用于返回循环中的重复项。
In [54]: a = itertools.cycle(['a','b','c'])
In [55]: a.next()
Out[55]: 'a'
In [56]: a.next()
Out[56]: 'b'
In [57]: a.next()
Out[57]: 'c'
In [58]: a.next()
Out[58]: 'a'
3、itertools.repeat(object[, times])
创建一个迭代器,重复生成object,times(如果已提供)指定重复计数,如果未提供times,将无止尽返回该对象。
In [67]: a = itertools.repeat('hello world',2)
In [68]: a
Out[68]: repeat('hello world', 2)
In [69]: a.next()
Out[69]: 'hello world'
In [70]: a.next()
Out[70]: 'hello world'
In [71]: a.next()
----------------------------------------------------------------------
-----StopIteration Traceback (most recent call
last)<ipython-input-71-aa817a57a973> in <module>()
----> 1 a.next()
StopIteration:
4、itertools.imap(function, *iterables)
创建一个迭代器,生成项function(i1, i2, ..., iN),其中i1,i2...iN分别来自迭代器iter1,iter2 ... iterN,如果function为None,则返回(i1, i2, ..., iN)形式的元组,只要提供的一个迭代器不再生成值,迭代就会停止。
即:返回一个迭代器, 它是调用了一个其值在输入迭代器上的函数, 返回结果. 它类似于内置函数 map() , 只是前者在任意输入迭代器结束后就停止(而不是插入None值来补全所有的输入).
返回序列每个元素被func执行后返回值的序列的迭代器,很像map()函数。
In [11]: a = itertools.imap(lambda x,y:(x,y,x+y),xrange(5),xrang
e(5,10))
In [12]: a.next()
Out[12]: (0, 5, 5)
In [13]: a.next()
Out[13]: (1, 6, 7)
In [14]: a.next()
Out[14]: (2, 7, 9)
5、itertools.chain(*iterables)
将多个迭代器作为参数, 但只返回单个迭代器, 它产生所有参数迭代器的内容, 就好像他们是来自于一个单一的序列。
from itertools import * for i in chain([1, 2, 3], ['a', 'b', 'c']): print i 1 2 3 a b c from itertools import chain, imap def flatmap(f, items): return chain.from_iterable(imap(f, items)) >>> list(flatmap(os.listdir, dirs)) >>> ['settings.py', 'wsgi.py', 'templates', 'app.py', 'templates', 'index.html, 'config.json']
6、itertools.dropwhile(predicate, iterable)
创建一个迭代器,只要函数predicate(item)为True,就丢弃iterable中的项,如果predicate返回False,就会生成iterable中的项和所有后续项。
即:在条件为false之后的第一次, 返回迭代器中剩下来的项.
from itertools import * def should_drop(x): print 'Testing:', x return (x<1) for i in dropwhile(should_drop, [ -1, 0, 1, 2, 3, 4, 1, -2 ]): print 'Yielding:', i Testing: -1 Testing: 0 Testing: 1 Yielding: 1 Yielding: 2 Yielding: 3 Yielding: 4 Yielding: 1 Yielding: -2
7、itertools.groupby(iterable[, key])
返回一个产生按照key进行分组后的值集合的迭代器.
如果iterable在多次连续迭代中生成了同一项,则会定义一个组,如果将此函数应用一个分类列表,那么分组将定义该列表中的所有唯一项,key(如果已提供)是一个函数,应用于每一项,如果此函数存在返回值,该值将用于后续项而不是该项本身进行比较,此函数返回的迭代器生成元素(key, group),其中key是分组的键值,group是迭代器,生成组成该组的所有项。
即:按照keyfunc函数对序列每个元素执行后的结果分组(每个分组是一个迭代器), 返回这些分组的迭代器。
from itertools import groupby qs = [{'date' : 1},{'date' : 2}] [(name, list(group)) for name, group in itertools.groupby(qs, lambda p:p['date'])] Out[77]: [(1, [{'date': 1}]), (2, [{'date': 2}])] >>> from itertools import * >>> a = ['aa', 'ab', 'abc', 'bcd', 'abcde'] >>> for i, k in groupby(a, len): ... print i, list(k) ... 2 ['aa', 'ab'] 3 ['abc', 'bcd'] 5 ['abcde']
8、itertools.ifilter(predicate, iterable)
返回的是迭代器类似于针对列表的内置函数 filter() , 它只包括当测试函数返回true时的项. 它不同于 dropwhile()
创建一个迭代器,仅生成iterable中predicate(item)为True的项,如果predicate为None,将返回iterable中所有计算为True的项
对函数func执行返回真的元素的迭代器。
from itertools import * def check_item(x): print 'Testing:', x return (x<1) for i in ifilter(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]): print 'Yielding:', i Testing: -1 Yielding: -1 Testing: 0 Yielding: 0 Testing: 1 Testing: 2 Testing: 3 Testing: 4 Testing: 1 Testing: -2 Yielding: -2
9、itertools.ifilterfalse(predicate, iterable)
和ifilter(函数相反 , 返回一个包含那些测试函数返回false的项的迭代器)
创建一个迭代器,仅生成iterable中predicate(item)为False的项,如果predicate为None,则返回iterable中所有计算为False的项 对函数func执行返回假的元素的迭代器。
from itertools import * def check_item(x): print 'Testing:', x return (x<1) for i in ifilterfalse(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]): print 'Yielding:', i Testing: -1 Testing: 0 Testing: 1 Yielding: 1 Testing: 2 Yielding: 2 Testing: 3 Yielding: 3 Testing: 4 Yielding: 4 Testing: 1 Yielding: 1 Testing: -2
10、itertools.islice(iterable, stop)
itertools.islice(iterable, start, stop[, step])
返回的迭代器是返回了输入迭代器根据索引来选取的项
创建一个迭代器,生成项的方式类似于切片返回值: iterable[start : stop : step],将跳过前start个项,迭代在stop所指定的位置停止,step指定用于跳过项的步幅。 与切片不同,负值不会用于任何start,stop和step, 如果省略了start,迭代将从0开始,如果省略了step,步幅将采用1.
返回序列seq的从start开始到stop结束的步长为step的元素的迭代器。
from itertools import * print 'Stop at 5:' for i in islice(count(), 5): print i print 'Start at 5, Stop at 10:' for i in islice(count(), 5, 10): print i print 'By tens to 100:' for i in islice(count(), 0, 100, 10): print i Stop at 5: 0 1 2 3 4 Start at 5, Stop at 10: 5 6 7 8 9 By tens to 100: 0 10 20 30 40 50 60 70 80 90
11、itertools.starmap(function, iterable)
创建一个迭代器,生成值func(*item),其中item来自iterable,只有当iterable生成的项适用于这种调用函数的方式时,此函数才有效。
对序列seq的每个元素作为func的参数列表执行, 返回执行结果的迭代器。
from itertools import * values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)] for i in starmap(lambda x,y:(x, y, x*y), values): print '%d * %d = %d' % i 0 * 5 = 0 1 * 6 = 6 2 * 7 = 14 3 * 8 = 24 4 * 9 = 36
12、itertools.tee(iterable[, n=2])
返回一些基于单个原始输入的独立迭代器(默认为2). 它和Unix上的tee工具有点语义相似, 也就是说它们都重复读取输入设备中的值并将值写入到一个命名文件和标准输出中
从iterable创建n个独立的迭代器,创建的迭代器以n元组的形式返回,n的默认值为2,此函数适用于任何可迭代的对象,但是,为了克隆原始迭代器,生成的项会被缓存,并在所有新创建的迭代器中使用,一定要注意,不要在调用tee()之后使用原始迭代器iterable,否则缓存机制可能无法正确工作。
把一个迭代器分为n个迭代器, 返回一个元组.默认是两个
from itertools import * r = islice(count(), 5) i1, i2 = tee(r) for i in i1: print 'i1:', i for i in i2: print 'i2:', i i1: 0 i1: 1 i1: 2 i1: 3 i1: 4 i2: 0 i2: 1 i2: 2 i2: 3 i2: 4
13、itertools.takewhile(predicate, iterable)
和dropwhile相反
创建一个迭代器,生成iterable中predicate(item)为True的项,只要predicate计算为False,迭代就会立即停止。
即:从序列的头开始, 直到执行函数func失败。
from itertools import * def should_take(x): print 'Testing:', x return (x<2) for i in takewhile(should_take, [ -1, 0, 1, 2, 3, 4, 1, -2 ]): print 'Yielding:', i Testing: -1 Yielding: -1 Testing: 0 Yielding: 0 Testing: 1 Yielding: 1 Testing: 2
14、itertools.izip(*iterables)
返回一个合并了多个迭代器为一个元组的迭代器. 它类似于内置函数zip(), 只是它返回的是一个迭代器而不是一个列表
创建一个迭代器,生成元组(i1, i2, ... iN),其中i1,i2 ... iN 分别来自迭代器iter1,iter2 ... iterN,只要提供的某个迭代器不再生成值,迭代就会停止,此函数生成的值与内置的zip()函数相同。
from itertools import * for i in izip([1, 2, 3], ['a', 'b', 'c']): print i (1, 'a') (2, 'b') (3, 'c')
15、itertools.izip_longest(*iterables[, fillvalue])
与izip()相同,但是迭代过程会持续到所有输入迭代变量iter1,iter2等都耗尽为止,如果没有使用fillvalue关键字参数指定不同的值,则使用None来填充已经使用的迭代变量的值。
class ZipExhausted(Exception): pass def izip_longest(*args, **kwds): # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- fillvalue = kwds.get('fillvalue') counter = [len(args) - 1] def sentinel(): if not counter[0]: raise ZipExhausted counter[0] -= 1 yield fillvalue fillers = repeat(fillvalue) iterators = [chain(it, sentinel(), fillers) for it in args] try: while iterators: yield tuple(map(next, iterators)) except ZipExhausted: pass
更多请参考http://wklken.me/posts/2013/08/20/python-extra-itertools.html (这里偷懒粘贴复制了)