列表推导式(list comprehension) 也成为列表解析式,可以使用非常简洁的方式对列表或其他可迭代对象的元素进行遍历、过滤或再次计算,快速生成满足特定需求的新列表,代码非常简洁,具有很强的可读性,是 python 程序开发过程时应用最多的技术之一。Python 的内部实现对列表推导式做了大量语法优化,可以保证很快的运行速度,也是推荐使用的一种技术。
列表推导式在逻辑上等价于一个循环语句,只是在形式上更加简洁。
x = [x * x for x in range(10)]
print(x)
# 等价于
x = []
for i in range(10):
x.append(i * i)
print(x)
y = ['banana', 'loganberry', 'passion fruit']
print([i.strip() for i in y])
# 等价于
z = []
for i in y:
z.append(i.strip())
print(z)
# 等价于
print(list(map(lambda i: i.strip(), y)))
print(list(map(str.strip, y)))
1 实现嵌套列表的平铺
列表推导式中有两个循环,第一个循环可以看作外循环,执行得慢;第二个循环可以看作内循环,执行得快。
from itertools import chain
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print([j for i in vec for j in i])
# 等价于
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
s = []
for i in vec:
for j in i:
s.append(j)
print(s)
print(list(chain(*vec)))
如果有多级嵌套或者不同子列表嵌套深度不同,就不能使用上面的方法了。这时,可以使用函数递归实现。
def flat_list(s):
g = [] # 存放最终结果的列表
def nested(s): # 函数嵌套定义
for i in s:
if isinstance(i, list):
nested(i) # 递归子列表
else:
g.append(i) # 扁平化列表
nested(s) # 调用嵌套定义的函数
return g # 返回结果
vec = [[1], [1, 'g'], ['a'], [], [12, 24]]
print(flat_list(vec))
2 过滤不符合条件的语句
在列表推导式中可以使用 if 子句对列表中的元素进行筛选,只在结果列表中保留符合条件的元素。
vec = [-1, -4.6, 7.5, -2.3, 9, -11]
print([i for i in vec if i > 0]) # 所有大于 0 的数字
scores = {'zs': 45, 'ls': 78, 'ww': 40, 'zl': 96,
'zq': 65, 'sb': 90, 'zj': 78, 'ws': 99, 'ds': 60}
highest = max(scores.values()) # 最高分
lowest = min(scores.values()) # 最低分
avg = sum(scores.values()) / len(scores) # 平均分
print(highest, lowest, avg)
highest_person = [name for name, score in scores.items() if score == highest]
print(highest_person)
from random import randint
# 使用列表推导式查找列表中最大元素的所有位置
x = [randint(10, 100) for i in range(10)] # 10个介于[10,100]之间的整数
print(x)
print([index for index, value in enumerate(x) if value == max(x)])
3 同时遍历多个列表或可迭代对象
对于包含多个循环的列表推导式,一定要清楚多个循环的执行顺序或 “嵌套关系”。
print([(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y])
# 等价于
g = []
for x in [1, 2, 3]:
for y in [3, 1, 4]:
if x != y:
g.append((x, y))
print(g)
print([(x, y) for x in [1, 2, 3] if x == 1 for y in [3, 1, 4] if x != y])
4 使用列表推导式实现矩阵转置
对于嵌套了列表推导式的列表推导式,一定要清楚其执行顺序。
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
print(matrix)
print([[row[i] for row in matrix] for i in range(4)])
# 等价于
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
g = []
for i in range(4):
g.append([row[i] for row in matrix])
print(g)
# 等价于
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
g = []
for i in range(4):
temp = []
for row in matrix:
temp.append(row[i])
g.append(temp)
print(g)
可以使用内置函数 zip() 和 list() 来实现矩阵转置。
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
print(list(map(list, zip(*matrix))))
5 列表推导式中可以使用函数或复杂表达式
def func(v):
if v % 2 == 0:
v = v ** 2
else:
v = v + 1
return v
print([func(v) for v in [2, 3, 4, -1] if v > 0])
# 等价于
print([v ** 2 if v % 2 == 0 else v + 1 for v in [2, 3, 4, -1] if v > 0])
6 列表推导式支持文件对象迭代
with open('test.txt', 'r') as fp:
print([line for line in fp])
7 使用列表推导式生成 100 以内的所有素数
from math import sqrt
print([x for x in range(2, 100) if 0 not in
[x % d for d in range(2, int(sqrt(x)) + 1)]])