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