Python的“Itertools”¶
Python的itertools模组提供了一套快速的高效使用内存的创建迭代器的核心工具。我会将在本节快速地展示一些itertool的工具。大部分这些函数都会创建生成器,因此我们将会需要迭代这些生成器才能展示它们的使用方法。此模组极其有用——本文强烈建议你花一些时间去了解该模组的内容。
Python有三个属于itertools的内置函数 range
,enumerate
,zip
,但因为它们极其有用,所以Python允许你在不导入它们的情况下直接就可以使用这些函数。熟练使用 range
,enumerate
,和 zip
是很重要的技能。
range
生成包含描述的“界限”(range)中的整数列表:
# 将会生成 0.. 1.. 2.. ... 8.. 9
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 将会生成 0.. 3.. 6.. 9
>>> range(0, 10, 3)
range(0, 10, 3)
>>> list(range(0, 10, 3))
[0, 3, 6, 9]
enumerate
枚举可迭代物中的对象:每轮迭代提供一元组,其内容为迭代轮数(从0开始)以及对应的可迭代物成员。
# 将会生成 (0, 'apple').. (1, 'banana').. (2, 'cat').. (3, 'dog')]
>>> enumerate(["apple", "banana", "cat", "dog"])
<enumerate at 0x23e3557b3f0>
>>> list(enumerate(["apple", "banana", "cat", "dog"]))
[(0, 'apple'), (1, 'banana'), (2, 'cat'), (3, 'dog')]
zip
将多个可迭代物的对应成员拉链(zip)到元组中。这为凑对多个可迭代物中对象很有用。
>>> names = ["Angie", "Brian", "Cassie", "David"]
>>> exam_1_scores = [90, 82, 79, 87]
>>> exam_2_scores = [95, 84, 72, 91]
# 将会生成 ('Angie', 90, 95).. ('Brian', 82, 84).. ('Cassie', 79, 72).. ('David', 87, 91)]
>>> zip(names, exam_1_scores, exam_2_scores)
<zip at 0x20de1082608>
>>> list(zip(names, exam_1_scores, exam_2_scores))
[('Angie', 90, 95), ('Brian', 82, 84), ('Cassie', 79, 72), ('David', 87, 91)]
以下是一些 itertools
模组中有用的函数:
itertools.chain
将多个可迭代物背靠背连接在一起,返回单个可迭代物:
>>> from itertools import chain
>>> gen_1 = range(0, 5, 2) # 0.. 2.. 4
>>> gen_2 = (i**2 for i in range(3, 6)) # 9.. 16.. 25
>>> iter_3 = ["moo", "cow"]
>>> iter_4 = "him"
# 将会生成:0.. 2.. 4.. 9.. 16.. 25.. 'moo'.. 'cow'.. 'h'.. 'i'.. 'm'
>>> chain(gen_1, gen_2, iter_3, iter_4)
<itertools.chain at 0x20de109ec18>
itertools.combinations 生成所有长度为n的可迭代物成员“组合”:
>>> from itertools import combinations
# 将会生成:(0, 1, 2).. (0, 1, 3).. (0, 2, 3).. (1, 2, 3)
>>> combinations([0, 1, 2, 3], 3) # 从 [0, 1, 2, 3] 的数字生成所有长度为3的组合
<itertools.combinations at 0x20de10a7728>
阅读理解:Itertools第一部分
使用 itertools.combinations
函数来找出从列表 ["apples", "bananas", "pears", "pears", "oranges"]
随机选择两个成员会提供“apples”和“pears”组合的几率。
阅读理解:Itertools第二部分
设列表 x_vals = [0.1, 0.3, 0.6, 0.9]
,创建一个生成器 y_gen
来生成 \(y = x^2\) 在每一个 \(x\) 对应的的y值。然后,使用 zip
来创建一个包含 \((x, y)\) 元组的列表。
阅读理解答案¶
Itertools第一部分:解
>>> from itertools import combinations
>>> ls = ["apples", "bananas", "pears", "pears", "oranges"]
>>> comb_ls = list(combinations(ls, 2))
>>> comb_ls.count(("apples", "pears")) / len(comb_ls)
0.2
Itertools第二部分:解
>>> x_vals = [0.1, 0.3, 0.6, 0.9]
>>> y_gen = (x**2 for x in x_vals)
>>> list(zip(x_vals, y_gen))
[(0.1, 0.01), (0.3, 0.09), (0.6, 0.36), (0.9, 0.81)]
在这个情况下,使用 zip
其实有点没必要的复杂化了。我们完全可以跳过创建 y_gen
并使用列表理解:
>>> x_vals = [0.1, 0.3, 0.6, 0.9]
>>> [(x, x**2) for x in x_vals]
[(0.1, 0.01), (0.3, 0.09), (0.6, 0.36), (0.9, 0.81)]