當使用iterator寫一些刁鑽的程式碼時,itertools也許會有現成的工具。
import itertools
it = itertools.chain([1, 2, 3], [4, 5, 6])
print(list(it))
# [1, 2, 3, 4, 5, 6]
it = itertools.repeat('hello', 3)
print(list(it))
# ['hello', 'hello', 'hello']
it = itertools.cycle([1, 2])
result = [next(it) for _ in range(10)]
print(result)
# [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
it1, it2, it3 = itertools.tee(['first', 'second'], 3)
print(list(it1))
print(list(it2))
print(list(it3))
['first', 'second']
['first', 'second']
['first', 'second']
tee可以平行生出多個iterators,但要小心記憶體可能會使用很多。
keys = ['one', 'two', 'three']
values = [1, 2]
normal = list(zip(keys, values))
print('zip: ', normal)
it = itertools.zip_longest(keys, values, fillvalue='nope')
print('zip_longest:', list(it))
zip_longest類似內建的zip,只是zip會以最短的iterator回傳,而zip_longest會以最長的iterator回傳。預設會以None來補上缺值。
zip: [('one', 1), ('two', 2)]
zip_longest: [('one', 1), ('two', 2), ('three', 'nope')]
values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
first_five = itertools.islice(values, 5)
print('First five: ', list(first_five))
middle_odds = itertools.islice(values, 2, 8, 2)
print('Middle odds:', list(middle_odds))
First five: [1, 2, 3, 4, 5]
Middle odds: [3, 5, 7]
islice可以做出類似list的slice功能
values= [1, 2, 3, 4, 5, 4, 3, 2, 1]
it = itertools.takewhile(lambda x: x < 4, values)
print(list(it))
[1, 2, 3]
takewhile需要傳入一個callable object,當其回傳為False會停止iterator。另外有一個dropwhile會從其回傳True的時候開始iterator。
evens = lambda x: x % 2 == 0
filter_result = filter(evens, values)
print('Filter: ', list(filter_result))
filter_false_result = itertools.filterfalse( evens, values)
print('Filter false: ', list(filter_false_result))
Filter: [2, 4, 4, 2]
Filter false: [1, 3, 5, 3, 1]
filter_false就是內建的filter的相反。