跳到主要内容

列表生成式

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 = 筛选条件,不能带 elsefor 前面的 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))。