列表生成式
1. 什么是列表生成式
- 列表生成式(List Comprehensions):Python 内置的、用一行根据规则创建 list 的写法。
- 用表达式 + for 代替多行循环,代码更短、更清晰。
2. 基本语法
- 形式:[ 表达式 for 变量 in 可迭代对象 ]
- 把要生成的元素(表达式)放前面,后面跟 for 循环;等价于:对每个 x 算出表达式,组成新 list。
# 循环写法
L = []
for x in range(1, 11):
L.append(x * x)
# L = [1, 4, 9, ..., 100]
# 列表生成式:一行代替
[x * x for x in range(1, 11)] # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
3. for 后面加 if(筛选)
- for 后面可加 if,作为筛选条件:只保留满足条件的元素。
- 注意:这里的 if 不能带 else(否则无法表示“筛掉谁”)。
[x * x for x in range(1, 11) if x % 2 == 0] # 仅偶数的平方:[4, 16, 36, 64, 100]
4. for 前面的 if ... else(表达式)
- for 前面可以是 if ... else 表达式:根据条件算出每个元素的值。
- 注意:这里的 if 必须带 else,否则表达式不完整,会 SyntaxError。
# 错误:for 前的 if 没有 else
# [x if x % 2 == 0 for x in range(1, 11)] # SyntaxError
# 正确:if ... else 得到确定结果
[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 = 表达式,必须带 else。
5. 两层 for(全排列)
- 可写多个 for,从左到右嵌套;常用于全排列、笛卡尔积。
[m + n for m in 'ABC' for n in 'XYZ']
# ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
- 三层及以上很少用。
6. 常见用法
| 场景 | 示例 |
|---|---|
| 目录列表 | [d for d in os.listdir('.')] |
| dict 转 list | [k + '=' + v for k, v in d.items()] |
| 字符串变小写 | [s.lower() for s in L] |
d = {'x': 'A', 'y': 'B', 'z': 'C'}
[k + '=' + v for k, v in d.items()] # ['y=B', 'x=A', 'z=C'](顺序可能不同)
L = ['Hello', 'World', 'IBM', 'Apple']
[s.lower() for s in L] # ['hello', 'world', 'ibm', 'apple']
7. 混合类型与筛选
- 若 list 中既有字符串又有整数等,直接写
[s.lower() for s in L]会报错(int 没有 lower)。 - 用 for 后面的 if 只保留字符串:
[s.lower() for s in L if isinstance(s, str)]。
L1 = ['Hello', 'World', 18, 'Apple', None]
L2 = [s.lower() for s in L1 if isinstance(s, str)] # ['hello', 'world', 'apple']
小结
| 写法 | 含义 |
|---|---|
[x for x in ...] | 对每个 x 取 x,组成 list |
[expr for x in ...] | 对每个 x 取 expr,组成 list |
[... for x in ... if 条件] | 只保留满足条件的 x(if 不能带 else) |
[a if 条件 else b for x in ...] | 每个元素按条件取 a 或 b(if 必须带 else) |
[expr for m in A for n in B] | 两层循环,全排列/笛卡尔积 |
- for 后的 if:筛选,不能 else。
- for 前的 if-else:表达式,必须 else。
- 列表生成式可从一个 list 推导出另一个 list,代码简洁。
练习:L1 = ['Hello','World',18,'Apple',None],用列表生成式得到只含字符串小写的 list:['hello','world','apple'](加 if isinstance(s, str))。