Modules and the standard libraryChapter 76 of 114
itertools
Building blocks for looping, that never build the whole sequence.
Everything here is lazy
itertools functions return iterators. Nothing is computed until you ask, and nothing is stored, so they work on inputs far larger than memory. Wrap in list() to see one.
chain: treat several sequences as one
from itertools import chain
print(list(chain([1, 2], [3], [4, 5])))
groups = [[1, 2], [3], [4, 5]]
print(list(chain.from_iterable(groups)))Output
[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
chain.from_iterable is the flattener, and unlike [x for g in groups for x in g] it never builds the intermediate list.
islice: a slice for anything
You cannot write gen[:5] on a generator. islice is the slice that works:
from itertools import islice, count
print(list(islice(count(1), 5)))
print(list(islice("abcdefgh", 2, 6)))
print(list(islice(range(10), 0, 10, 3)))Output
[1, 2, 3, 4, 5] ['c', 'd', 'e', 'f'] [0, 3, 6, 9]
count(1) is endless. Taking five from it costs five.
The endless three
from itertools import count, cycle, repeat, islice
print(list(islice(count(10, 5), 4)))
print(list(islice(cycle("ab"), 5)))
print(list(repeat("x", 3)))Output
[10, 15, 20, 25] ['a', 'b', 'a', 'b', 'a'] ['x', 'x', 'x']
Always pair count and cycle with something that stops, or the loop never ends.
accumulate: running totals
from itertools import accumulate
print(list(accumulate([1, 2, 3, 4])))
print(list(accumulate([1, 2, 3, 4], max)))
print(list(accumulate([3, 1, 4], initial=0)))Output
[1, 3, 6, 10] [1, 2, 3, 4] [0, 3, 4, 8]
groupby: runs of equal items
The one that surprises people: it groups consecutive items, so sort first if you want all of a kind together.
from itertools import groupby
data = ["apple", "avocado", "banana", "blueberry", "apricot"]
for letter, group in groupby(data, key=lambda w: w[0]):
print(letter, list(group))Output
a ['apple', 'avocado'] b ['banana', 'blueberry'] a ['apricot']
a appeared twice, because "apricot" was not next to the others. Sorting by the same key fixes it:
from itertools import groupby
data = ["apple", "avocado", "banana", "apricot"]
data.sort(key=lambda w: w[0])
for letter, group in groupby(data, key=lambda w: w[0]):
print(letter, list(group))Output
a ['apple', 'avocado', 'apricot'] b ['banana']
The sort is stable, so inside the a run the words keep the order they had in the original list rather than becoming alphabetical.
Combinations and permutations
from itertools import combinations, permutations, product
print(list(combinations("abc", 2)))
print(list(permutations("abc", 2)))
print(list(product([1, 2], "ab")))Output
[('a', 'b'), ('a', 'c'), ('b', 'c')]
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]Combinations ignore order; permutations do not. product is the nested loop: product(a, b) is every pairing, and repeat= gives you a loop of loops.
from itertools import product
print(list(product([0, 1], repeat=2)))Output
[(0, 0), (0, 1), (1, 0), (1, 1)]
Filtering pairs
from itertools import takewhile, dropwhile, compress
numbers = [1, 2, 3, 10, 1]
print(list(takewhile(lambda n: n < 5, numbers)))
print(list(dropwhile(lambda n: n < 5, numbers)))
print(list(compress("abcd", [1, 0, 1, 0])))Output
[1, 2, 3] [10, 1] ['a', 'c']
takewhile stops at the first failure, unlike filter, which checks everything. Note the trailing 1 survived dropwhile: once it starts yielding, it never tests again.
pairwise
from itertools import pairwise
readings = [10, 12, 11, 15]
print(list(pairwise(readings)))
print([b - a for a, b in pairwise(readings)])Output
[(10, 12), (12, 11), (11, 15)] [2, -1, 4]
Differences between neighbours, without any index arithmetic.
Test yourself
2 questionsWhy does groupby show the same key twice sometimes?
Show the answer
It groups consecutive items, so you must sort first — Sort by the same key you group by, and each key appears once.
How do you take the first five items of an endless generator?
Show the answer
islice(source, 5) — You cannot slice a generator, and list() on an endless one never returns.
os and sys
Talk to the operating system: environment, paths, and the running interpreter.