使用嵌套循环列出理解

List Comprehensions 可以使用嵌套的 for 循环。你可以在列表推导中编码任意数量的嵌套 for 循环,并且每个 for 循环可以具有可选的关联 if 测试。这样做时,for 构造的顺序与编写一系列嵌套的 for 语句时的顺序相同。列表推导的一般结构如下所示:

[ expression for target1 in iterable1 [if condition1]
             for target2 in iterable2 [if condition2]...
             for targetN in iterableN [if conditionN] ]

例如,以下代码使用多个 for 语句展平列表列表:

data = [[1, 2], [3, 4], [5, 6]]
output = []
for each_list in data:
    for element in each_list:
        output.append(element)
print(output)
# Out: [1, 2, 3, 4, 5, 6]

可以等效地编写为具有多个 for 构造的列表理解:

data = [[1, 2], [3, 4], [5, 6]]
output = [element for each_list in data for element in each_list]
print(output)
# Out: [1, 2, 3, 4, 5, 6]

现场演示

在扩展形式和列表理解中,外部循环(首先是语句)首先出现。

除了更紧凑之外,嵌套理解也明显更快。

In [1]: data = [[1,2],[3,4],[5,6]]
In [2]: def f():
   ...:     output=[]
   ...:     for each_list in data:
   ...:         for element in each_list:
   ...:             output.append(element)
   ...:     return output
In [3]: timeit f()
1000000 loops, best of 3: 1.37 µs per loop
In [4]: timeit [inner for outer in data for inner in outer]
1000000 loops, best of 3: 632 ns per loop

上面函数调用的开销大约是 140ns

内联 ifs 嵌套类似,可能出现在第一个 for 之后的任何位置:

data = [[1], [2, 3], [4, 5]]
output = [element for each_list in data
                if len(each_list) == 2
                for element in each_list
                if element != 5]
print(output)
# Out: [2, 3, 4]

现场演示

但是,为了便于阅读,你应该考虑使用传统的 for 循环。当嵌套深度超过 2 级时,和/或理解的逻辑过于复杂时尤其如此。多个嵌套循环列表理解可能容易出错或者会产生意外结果。