defcycle(iterable): # cycle('ABCD') --> A B C D A B C D A B C D ... saved = [] for element in iterable: yield element saved.append(element) while saved: for element in saved: yield element
itertools.repeat(object[, times])
让迭代器一次又一次地返回对象。无限运行,除非指定了times参数控制重复次数
大致相当于:
1 2 3 4 5 6 7 8
defrepeat(object, times=None): # repeat(10, 3) --> 10 10 10 if times isNone: whileTrue: yieldobject else: for i inrange(times): yieldobject
defdropwhile(predicate, iterable): # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1 iterable = iter(iterable) for x in iterable: ifnot predicate(x): yield x break for x in iterable: yield x
itertools.filterfalse(predicate, iterable)
从迭代器中过滤出所有使predicate为False的元素,并返回 大致相当于:
1 2 3 4 5 6 7
deffilterfalse(predicate, iterable): # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 if predicate isNone: predicate = bool for x in iterable: ifnot predicate(x): yield x
groups = [] uniquekeys = [] data = sorted(data, key=keyfunc) for k, g in groupby(data, keyfunc): groups.append(list(g)) # Store group iterator as a list uniquekeys.append(k)
classgroupby: # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D def__init__(self, iterable, key=None): if key isNone: key = lambda x: x self.keyfunc = key self.it = iter(iterable) self.tgtkey = self.currkey = self.currvalue = object() def__iter__(self): return self def__next__(self): self.id = object() while self.currkey == self.tgtkey: self.currvalue = next(self.it) # Exit on StopIteration self.currkey = self.keyfunc(self.currvalue) self.tgtkey = self.currkey return (self.currkey, self._grouper(self.tgtkey, self.id)) def_grouper(self, tgtkey, id): while self.idisidand self.currkey == tgtkey: yield self.currvalue try: self.currvalue = next(self.it) except StopIteration: return self.currkey = self.keyfunc(self.currvalue)
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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']
defislice(iterable, *args): # islice('ABCDEFG', 2) --> A B # islice('ABCDEFG', 2, 4) --> C D # islice('ABCDEFG', 2, None) --> C D E F G # islice('ABCDEFG', 0, None, 2) --> A C E G s = slice(*args) start, stop, step = s.start or0, s.stop or sys.maxsize, s.step or1 it = iter(range(start, stop, step)) try: nexti = next(it) except StopIteration: # Consume *iterable* up to the *start* position. for i, element inzip(range(start), iterable): pass return try: for i, element inenumerate(iterable): if i == nexti: yield element nexti = next(it) except StopIteration: # Consume to *stop*. for i, element inzip(range(i + 1, stop), iterable): pass
如果start为None,那么迭代从0开始。如果step是None,那么step默认为1。
itertools.starmap(function, iterable)
将iterable中的每一项,映射到function中,并执行function 大致相当于:
1 2 3 4
defstarmap(function, iterable): # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 for args in iterable: yield function(*args)
deftee(iterable, n=2): it = iter(iterable) deques = [collections.deque() for i inrange(n)] defgen(mydeque): whileTrue: ifnot mydeque: # when the local deque is empty try: newval = next(it) # fetch a new value and except StopIteration: return for d in deques: # load it to all the deques d.append(newval) yield mydeque.popleft() returntuple(gen(d) for d in deques)
实际这样用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from itertools import tee
print(tee([1,2,3], 3)) # ==>(<itertools._tee object at 0x10cf787c8>, <itertools._tee object at 0x10cf78808>, <itertools._tee object at 0x10cf78848>)
for a in tee([1,2,3], 3): for i in a: print(i, end=" ") print() # 1 2 3 # 1 2 3 # 1 2 3
for a, b, c in tee([1,2,3], 3): print(a, b, c) # 1 2 3 # 1 2 3 # 1 2 3
大致相当于生成器表达式中的嵌套for循环。例如,product(A, B)的返回和((x,y) for x in A for y in B)一样
要计算iterable与其自身的乘积,请使用可选的repeat关键字参数指定重复次数。 例如,product(A, repeat=4)相当于product(A, A, A, A)
此函数大致等同于以下代码,但实际实现不会在内存中构建中间结果:
1 2 3 4 5 6 7 8 9
defproduct(*args, repeat=1): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = [tuple(pool) for pool in args] * repeat result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yieldtuple(prod)
defpermutations(iterable, r=None): # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC # permutations(range(3)) --> 012 021 102 120 201 210 pool = tuple(iterable) n = len(pool) r = n if r isNoneelse r if r > n: return indices = list(range(n)) cycles = list(range(n, n-r, -1)) yieldtuple(pool[i] for i in indices[:r]) while n: for i inreversed(range(r)): cycles[i] -= 1 if cycles[i] == 0: indices[i:] = indices[i+1:] + indices[i:i+1] cycles[i] = n - i else: j = cycles[i] indices[i], indices[-j] = indices[-j], indices[i] yieldtuple(pool[i] for i in indices[:r]) break else: return
defcombinations(iterable, r): # combinations('ABCD', 2) --> AB AC AD BC BD CD # combinations(range(4), 3) --> 012 013 023 123 pool = tuple(iterable) n = len(pool) if r > n: return indices = list(range(r)) yieldtuple(pool[i] for i in indices) whileTrue: for i inreversed(range(r)): if indices[i] != i + n - r: break else: return indices[i] += 1 for j inrange(i+1, r): indices[j] = indices[j-1] + 1 yieldtuple(pool[i] for i in indices)
defcombinations_with_replacement(iterable, r): # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC pool = tuple(iterable) n = len(pool) ifnot n and r: return indices = [0] * r yieldtuple(pool[i] for i in indices) whileTrue: for i inreversed(range(r)): if indices[i] != n - 1: break else: return indices[i:] = [indices[i] + 1] * (r - i) yieldtuple(pool[i] for i in indices)