列表解析的出现,对于Python来说,绝对算是一种革命性的变化。我们可以通过一种极其简洁的列表解析的式子,完成符合某种规律的列表的构建,或者替代函数式编程中 map(), filter()
这些函数的作用(函数式编程以后我会再做总结),实现对一个序列的筛选,依次计算等功能。
先来看看列表解析的语法:[expr for iter_val in iterable]
简单说,就是对于一个可迭代的对象中的每一个元素,通过表达式对该元素作用,得到一个计算结果,然后再通过for循环遍历这个可迭代对象的每一个元素,将作用后的结果构成一个列表。这个作用后的结果可能是由之前元素计算得到的新对象,也可能就是原先的元素。
概念本身没什么可多说的,但是太不直观。所以,我会举以下的例子说明列表解析到底是如何使用的。
给出一个序列,需要得到这个序列中的每一个数的平方
a = [1, 2, 3, 4, 5]
result = [x ** 2 for x in a] # x是元素,列表a是可迭代对象
print(result) # >>> [1, 4, 9, 16, 25]
当然,可迭代对象如果符合某种规律,也可以通过 range()
表达式表示
print([x + 1 for x in range(10)]) # >>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
表达式除了可以直接通过操作符书写,还可以是一个已经定义好的函数
def fun(num):
return 2 * num - 1
print([fun(x) for x in range(3, 10)]) # >>> [5, 7, 9, 11, 13, 15, 17]
其实也是对序列中每个元素进行计算,只不过起到的是筛选的功能
比如,现在想要筛选出2~30当中所有的素数,构成一个列表
import math
# 定义素性判断函数
def isPrime(num):
k = int(math.sqrt(num))
for i in range(2, k + 1):
if num % i == 0:
return False
return True
print([x for x in range(2, 31) if isPrime(x)]) # >>> [2, 3, 5, 7, 11, 13, 19, 23, 29]
现在,要做的事情是构建 2×3 2 × 3 个数对,形式如下:
(1,1),(1,2),(1,3),(2,1),(2,2),(2,3) ( 1 , 1 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 1 ) , ( 2 , 2 ) , ( 2 , 3 )
那么可以通过列表解析式,这样生成
[(x + 1, y + 1) for x in range(2) for y in range(3)]
当然,还可以通过列表解析来统计字符串的字符数
s = "I wrote Python"
print(sum([len(i) for i in s.split()])) # >>> 12
这个例子当中,先是通过 s.split()
构成序列,序列的每一个元素是字符串s的每一个单词,然后通过 [len(i) for i in s.split()]
生成由这些单词的长度构成的列表,最后通过 sum()
函数加和,可见,本来需要好几行代码才完成的工作,通过列表解析,我们只需要简单的1行代码。