除了基本的用法之外,列表推导也支持多重循环。例如,要把矩阵(也就是二维列表)简化成一维列表,使原来的每个单元格都成为新列表中的普通元素。这个功能采用包含两个for表达式的列表推导即可实现,这些for表达式会按照从左至右的顺序来评估。
matrix = [[1,2,3], [4,5,6], [7,8,9]]
flat = [x for row in matrix for x in row]
print(flat)
>>>
[1,2,3,4,5,6,7,8,9]
上面这个例子简单易易懂,这就是多重循环的合理用法。还有一种包含多重循环的合理用法,那就是根据输入列表来创建有两层深度的新列表。例如,我们要对二维矩阵的每个单元格取平方,然后用这些平方值构建新的矩阵。由于要多使用一对中括号,所以实现该功能的代码会经上例稍微复杂一点,但依然不难理解。
squared = [[x**2 for x in row] for row in matrix]
print(squared)
>>>
[[1,4,9],[16,25,36],[49,64,81]]
如果表达式里还有一层循环,那么列表推导就会变得很长,这时必须把它分成多行来写,才能看得清楚一些
my_lists = [
[[1,2,3], [4,5,6]],
[[2,3,4], [7,8,9]]
]
flat1 = [x for sublist1 in my_lists
for sublist2 in sublist1
for x in sublist2]
可以看出此时列表推导并不比普通写法更加简单,如果用普通写法的话:
flat2 = []
for sublist1 in my_lists:
for sublist2 in sublist1:
flat2.extend(sublist2)
print(flat2)
列表推导也支持多个if条件。处在同一循环级别中的多项条件,彼此之间默认形成and表达式。例如,要从数字列表中选出大于4的偶数,那么下面这两种列表推导方式是等效的。
a =[1,2,3,4,5,6,7,8,9,10]
b = [x for x in a if x>4 if x%2 == 0]
c = [x for x in a if x > 4 and x%2 == 0]
每一级循环的for表达式后面都可以指定条件。例如,要从原矩阵中把那些本身能为3所整除,且其所在行的各元素之和又大于等于10的单元格挑出来。我们只需编写很简短的代码,就可用列表推导来实现此功能,但是,这样的代码非常难懂。
matrix = [[1,2,3], [4,5,6], [7,8,9]]
filtered = [[x for x in row if x%3 == 0]
for row in matrix if sum(row) >= 10]
print(filtered)
>>>
[[6], [9]]
尽管这个例子稍微有点复杂 ,但在实际编程中,确实会出现这种看上云似乎适合用列表推导来实现 的情况 。强烈建议大家尽量不要编写 这种包含复杂 式子的列表推导。这么写虽然能省下几行空间,但却会给稍后阅读代码的人带来很大障碍。
在列表推导中,最好不要使用两个以上的表达式。可以使用两个条件、两个循环或一个条件搭配一个循环。如果要写的代码比较复杂,那就应该使用普通的if和for语句 ,并编写辅助函数。
要点:
- 列表推导支持多级循环,每一级循环也支持多项条件。
- 超过两个表达式的列表 推导是很难理解的,应该尽量避免。
个人评价:这条建议不是很重要,我在平时基本没用过两个以上表达式的列表推导,也很少在别人的代码中看到。