列表生成式

Python 内置的非常简单却强大的可以用来创建 list 的生成式。

使用场合

传统方法

1
2
3
L = []
for x in range(1, 11):
L.append(x * x)

列表生成式替代

1
L = [x * x for x in range(1,11)]

for 循环后面还可以加上 if 判断,这样我们就可以筛选出仅偶数的平方

1
L = [[x * x for x in range(1, 11) if x % 2 == 0]]

还可以使用两层循环,可以生成全排列:

1
2
3
L = [m + n for m in 'ABC' for n in 'XYZ']
print(L)
>>> ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

for 循环其实可以同时使用两个甚至多个变量,比如 dictitems() 可以同时迭代 keyvalue

1
2
3
4
5
6
d = {'x': 'A', 'y': 'B', 'z': 'C' }
for k, v in d.items():
print(k, '=', v)
>>> y = B
>>> x = A
>>> z = C

因此,列表生成式也可以使用两个变量来生成 list

1
2
3
d = {'x': 'A', 'y': 'B', 'z': 'C' }
[k + '=' + v for k, v in d.items()]
>>> ['y=B', 'x=A', 'z=C']

if … else

使用列表生成式的时候,有些童鞋经常搞不清楚 if...else 的用法

例如,以下代码正常输出偶数

1
2
>>> [x for x in range(1, 11) if x % 2 == 0]
[2, 4, 6, 8, 10]

但是,我们不能在最后的 if 加上 else

1
2
3
4
5
>>> [x for x in range(1, 11) if x % 2 == 0 else 0]
File "<stdin>", line 1
[x for x in range(1, 11) if x % 2 == 0 else 0]
^
SyntaxError: invalid syntax

这是因为跟在 for 后面的 if 是一个筛选条件,不能带 else,否则如何筛选

另一些童鞋发现把 if 写在 for 前面必须加 else,否则报错

1
2
3
4
5
>>> [x if x % 2 == 0 for x in range(1, 11)]
File "<stdin>", line 1
[x if x % 2 == 0 for x in range(1, 11)]
^
SyntaxError: invalid syntax

这是因为 for 前面的部分是一个表达式,它必须根据 x 计算出一个结果。因此,考察表达式:x if x % 2 == 0,它无法根据 x 计算出结果,因为缺少 else,必须加上 else

1
2
>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

可见,在一个列表生成式中,for 前面的 if ... else 是表达式,而 for 后面的 if 是过滤条件,不能带 else