列表解析是Python的一大特色,它让需要多行代码才能实现的列表创建工作用一行代码就能搞定!实际上,前面这句话只说对了90%,因为利用列表解析有时候并非为了创建一个列表,而仅仅是利用其简洁性推动某个循环(后面详细举例说明)来完成其他操作。更确切的表述应该是:列表解析让for循环更简洁!对,就是这样。
本文的目的,并非罗列列表解析的各种出色表现,而是简单分享利用列表解析所要注意的地方。大神可略过。
列表解析最基本的语法如下:
[expression for iter_val in iterable]
expression决定了新生成列表的元素是怎么来的,例如:
>>>a = [x**2 for x in range(10)]
>>>print(a)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
上例是列表解析最简单、最直观、最容易理解的形式,即新生成的list的每个元素由x**2组成。
>>>x = [-i if i%2==0 else i for i in range(10)]
>>>print(x)
[0, 1, -2, 3, -4, 5, -6, 7, -8, 9]
上例中expression是一个“if else”组成的判断语句,即当i为偶数时,取-i作为新生成列表的元素,否则取i。相比于前例,该例稍微复杂,但依然是列表解析的常规用法。
下面我们用实例说明,列表解析不止于此!
(1) 循环变量iter_val不一定非要在expression中
实际上循环变量iter_val仅仅只是为了驱动列表解析的执行,每循环一次expression便执行一次,至于iter_val是否会在expression中被用到则完全根据实际情况而定。例如:
>>>a = [1 for x in range(10)]
>>>print(a)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
这里,expression是一个常数1,跟循环变量x完全没有关系,x只是推动了列表的生成。
(2) 利用列表解析,但并不是为了得到它直接返回的列表
直接利用列表解析生成列表时,目标列表的每个元素是expression本身,即‘列表元素=expression’,对于x**2这种简单的数学表达式而言,它的返回值就是我们的目标值,这没什么问题。但是,当expression本身的返回值并不是我们的目标值时,列表解析式返回的列表就不是我们的目标列表了,例如:
>>>y1 = []
>>>y2 = [y1.append(x) for x in range(10)]
>>>print(y1)
>>>print(y2)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[None, None, None, None, None, None, None, None, None, None]
上例中相当于“expression=y1.append(x)”,y1.append(x)的作用是将x逐个加入y1的末尾,这是一种操作,该操作本身没有返回值(或者说返回值是None)(千万不要以为返回值是由x组成的列表),即相当于expression=None,所以最后y2的结果就全部是None,显然该例中列表解析本身产生的列表并非我们的目标,我们的目标是y1。
下面的例子更直观:
>>>seq = [print('python') for x in range(10)]
>>>print('seq={}'.format(seq))
python
python
python
python
python
python
python
python
python
python
seq=[None, None, None, None, None, None, None, None, None, None]
该列表解析是用print('python')输出10次python,它也是一种操作,也没有返回值(或者说返回值是None),即expression=None,结果seq是10个None。该例只是利用列表解析的简洁性来打印结果,并非为了得到列表本身。