Python推导式功能:一行代码搞定复杂逻辑

liftword3周前 (04-11)技术文章12

对话实录

小白:(抓狂)我写了 10 行循环,同事用 1 行就搞定了!

专家:(掏出魔杖)掌握推导式,代码瞬间瘦身

三大推导式

1. 列表推导式

传统写法需要先创建一个空列表,然后通过循环逐个计算并添加元素。

#  传统写法
squares = []
for x in range(5):
 squares.append(x**2)

而使用列表推导式,只需一行代码就能完成相同功能。

它的结构是[表达式 for 变量 in 可迭代对象] 或者 [表达式 for 变量 in 可迭代对象 if 条件表达式] 或者 [表达式A if 条件表达式 else 表达式B for 变量 in 可迭代对象]

#  推导式写法
squares = [x**2 for x in range(5)] # → [0,1,4,9,16]
squares = [x**2 for x in range(5) if x%2==0] # → [0,4,16]
squares = [x**2 if x%2==0 else x**3 for x in range(5) ] # → [0,1,4,27,16]

专家提醒:推导式比map+lambda更 Pythonic!map结合lambda也能实现类似功能,但代码相对更复杂,不够简洁直观,比如list(map(lambda x: x**2, range(5)))。

2. 字典推导式

传统方式构建字典,需要先初始化一个空字典,再通过循环逐个添加键值对。

#  传统写法
dict1 = {}
for x in range(5):
 dict1[x] = x**2

字典推导式的结构是{键表达式: 值表达式 for 变量 in 可迭代对象} 或者 {键表达式: 值表达式 for 变量 in 可迭代对象 if 条件表达式} 或者 {键表达式: 值表达式 if 条件表达式 else 值表达式 for 变量 in 可迭代对象},可以快速生成字典。

#  推导式写法
dict1 = {x: x**2 for x in range(5)} # → {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
dict2 = {x: x**2 for x in range(5) if x%2==0} # → {0:0,2:4,4:16}
dict3 = {x: x**2 if x%2==0 else x**3 for x in range(5)} # → {0: 0, 1: 1, 2: 4, 3: 27, 4: 16}

3. 集合推导式

传统方式构建集合,需要先初始化一个空集合,再通过循环逐个添加值。

#  传统写法
set1 = set() 
# 不能用set1={} 这是定义一个空字典
for x in range(5):
 set1.add(x**2) #-> {0, 1, 4, 9, 16}

集合推导式的结构是{表达式 for 变量 in 可迭代对象} 或者 {表达式 for 变量 in 可迭代对象 if 条件表达式} 或者 {表达式A if 条件表达式 else 表达式B for 变量 in 可迭代对象},可以快速生成集合。

# 推导式写法
set1 = {x**2 for x in range(5)} # → {0, 1, 4, 9, 16}
set2 = {x**2 for x in range(5) if x%2==0} # → {0, 4, 16}
set3 = {x**2 if x%2==0 else x**3 for x in range(5)} # → {0, 1, 4, 16, 27}

四大实战案例

案例 1:多重条件过滤

# 多重条件
nums = [x for x in range(20) if x%2==0 if x>10] # → [12,14,16,18]

案例 2:嵌套推导式

对于矩阵转置,传统方法较为复杂,需要嵌套循环。而嵌套推导式通过两层循环实现转置。外层循环遍历列索引,内层循环遍历行,根据行列索引获取元素组成新的矩阵。

# 矩阵转置
matrix = [[1,2,3],[4,5,6],[7,8,9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
# → [[1,4,7],[2,5,8],[3,6,9]]

案例 3:字典键值互换

传统方法需遍历字典,逐个交换键值对创建新字典。字典推导式则简洁很多,使用items()方法获取键值对,然后交换位置生成新字典。

data = {"a":1, "b":2, "c":3}
inverted = {v:k for k,v in data.items()} # → {1:"a",2:"b",3:"c"}

案例4:嵌套解包

在二维列表展开时,传统方法需要嵌套循环遍历。嵌套解包的推导式可以简洁地将二维列表扁平化。先遍历外层列表,再遍历内层列表,将元素逐个取出组成新列表。

# 二维列表展开
matrix = [[1,2],[3,4]]
flat = [x for row in matrix for x in row] # → [1,2,3,4]

三大血泪陷阱

过度嵌套

过度嵌套的推导式虽然代码简洁,但可读性极差,维护困难。

# 难以阅读的写法
result = [[x*y for y in range(10)] for x in range(10)]

建议拆分成更易读的形式,先创建外层列表,再在内层使用推导式填充。

# 建议拆分
rows = []
for x in range(10):
 row = [x*y for y in range(10)]
 rows.append(row)

副作用问题

推导式中对原列表进行修改会产生副作用,改变原数据结构,这通常不是我们期望的。

# 错误示范
[x.append(1) for x in [[], [], []]] # 修改了原列表!

正确做法是创建新列表,通过连接操作实现类似效果,不会影响原列表。

# 正确做法
new_lists = [x + [1] for x in [[], [], []]]

性能陷阱

错误的写法会导致性能问题,比如在大范围内进行不必要的查找判断。

# 错误示范
[x for x in range(10**6) if x in set(range(0,10**6,2))] # 慢!

应直接使用步长来生成符合条件的序列,避免不必要的集合操作,提升性能。

# 正确做法
[x for x in range(0,10**6,2)]

专家工具箱

1.生成器表达式

生成器表达式和列表推导式语法相似,只是把方括号换成圆括号。它不会一次性生成所有元素,而是按需生成,节省内存,适合处理大规模数据。使用next()函数可以逐个获取元素。

# 节省内存
squares = (x**2 for x in range(10**6))
print(next(squares)) # → 0


小白:(献上膝盖)原来推导式这么强大!

专家:(扶起小白)记住:推导式是 Python 的语法糖,但别贪吃哦!

相关文章

python zip函数可以实现同时遍历多列表,以及矩阵转置等

zip 函数是Python的内置函数,用于将多个可迭代对象中对应位置的元素打包成元组,并返回一个由这些元组组成的迭代器。 概念看不懂没关系,我们来举个简单例子。比如有两个列表x=["a","b","c...

矩阵的转置

有关矩阵的讲解,在之前我已经提过了,矩阵是一个数表,大家一定要记清楚!下面我们来说一说矩阵的转置,首先来了解一下定义:定义:把一个m×n矩阵A的行换成同序数的列而得到的n×m矩阵,称为矩阵A的转置矩阵...

C++矩阵转置

C++矩阵转置看了很多网山有关矩阵转置的代码,大部分还用了中间变量,本人亲测矩阵转置代码无误,望对广大C++初学者有所帮助!题目如下:写一个函数,使给定的一个二维数组(3x3)转置,即行列互换。Inp...

4.NumPy数组操作

4.NumPy数组操作4.1改变NumPy数组维度前面已经学习了怎样使用reshape函数,接下来我们来学习展开数组ravelravel函数完成展平数组的操作。import numpy as npb...

Python中zip()函数详解:合并、解压与高效数据处理

在Python中,zip() 是一个非常实用的内置函数,用于将多个可迭代对象(如列表、元组、字符串等)合并成一个元组的列表。它通过将输入的每个可迭代对象的元素按位置配对,生成一个迭代器,其中每个元素是...

C++矩阵求转置矩阵

n阶矩阵求转置,也就是沿着左对角线反转矩阵;a[i][j] 与 a[j][i] 对换。算法实现:n * m矩阵的转置,行和列颠倒。算法实现:最后,如果你想学C/C++可以私信小编“01”获取素材资料以...