使用巢狀迴圈列出理解

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 級時,和/或理解的邏輯過於複雜時尤其如此。多個巢狀迴圈列表理解可能容易出錯或者會產生意外結果。