【python】python进阶——推导式

目录

一、推导式介绍

二、推导式的用法

[2.1 列表推导式](#2.1 列表推导式)

[2.2 字典推导式](#2.2 字典推导式)

[2.3 集合推导式](#2.3 集合推导式)

[2.4 生成器表达式](#2.4 生成器表达式)

三、推导式的嵌套和复杂用法

[3.1 嵌套推导式](#3.1 嵌套推导式)

[3.2 多重条件推导式](#3.2 多重条件推导式)

四、推导式对比传统循环

[4.1 性能比较](#4.1 性能比较)

[4.2 可读性比较](#4.2 可读性比较)

五、常见应用场景

[5.1 数据清洗和转换](#5.1 数据清洗和转换)

[5.2 文件处理](#5.2 文件处理)

[5.3 API数据处理](#5.3 API数据处理)

六、注意事项

参考


一、推导式介绍

Python推导式(Comprehension)是一种简洁、优雅的语法结构,可以用单行代码快速创建列表、字典、集合等数据结构。它基于现有的可迭代对象,通过表达式和条件语句来生成新的数据集合。

不仅让代码更加简洁易读,而且在大多数情况下比传统的循环方式执行效率更高。

二、推导式的用法

Python 推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。

Python 支持推导式的数据结构有:

  • 列表(list)推导式
  • 字典(dict)推导式
  • 集合(set)推导式
  • 元组(tuple)推导式

2.1 列表推导式

列表推导式是最常见的形式,用于创建新的列表。

基本语法:

python 复制代码
[expression for item in iterable if condition]

示例:

python 复制代码
# 传统方式
squares = []
for x in range(10):
    squares.append(x**2)

# 列表推导式
squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

带条件的列表推导式:

python 复制代码
# 只保留偶数平方
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# 使用条件表达式
results = ["偶数" if x % 2 == 0 else "奇数" for x in range(5)]
print(results)  # ['偶数', '奇数', '偶数', '奇数', '偶数']

嵌套循环的列表推导式:

python 复制代码
# 生成所有可能的坐标对
coordinates = [(x, y) for x in range(3) for y in range(3)]
print(coordinates)  # [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

2.2 字典推导式

字典推导式用于创建字典,语法与列表推导式类似。

基本语法:

python 复制代码
{key_expression: value_expression for item in iterable if condition}

示例:

python 复制代码
# 创建数字到其平方的映射
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 反转字典的键和值
original = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {v: k for k, v in original.items()}
print(reversed_dict)  # {1: 'a', 2: 'b', 3: 'c'}

# 带条件的字典推导式
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
print(even_squares)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

2.3 集合推导式

集合推导式用于创建集合,会自动去除重复元素。

基本语法:

python 复制代码
{expression for item in iterable if condition}

示例:

python 复制代码
# 从列表中创建不重复的平方数集合
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_squares = {x**2 for x in numbers}
print(unique_squares)  # {16, 1, 9, 4}

# 带条件的集合推导式
even_squares = {x**2 for x in range(10) if x % 2 == 0}
print(even_squares)  # {0, 64, 4, 36, 16}

2.4 生成器表达式

生成器表达式使用圆括号,与列表推导式类似,但返回一个生成器对象,按需生成值,节省内存。

基本语法:

python 复制代码
(expression for item in iterable if condition)

示例:

python 复制代码
# 创建生成器
squares_gen = (x**2 for x in range(10))

# 使用生成器
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

# 可以转换为列表
print(list(squares_gen))  # [4, 9, 16, 25, 36, 49, 64, 81]

# 在函数中使用
total = sum(x**2 for x in range(10))
print(total)  # 285

三、推导式的嵌套和复杂用法

3.1 嵌套推导式

python 复制代码
# 二维列表展平
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

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

3.2 多重条件推导式

python 复制代码
# 多个条件
numbers = [x for x in range(20) if x % 2 == 0 if x % 3 == 0]
print(numbers)  # [0, 6, 12, 18]

# 复杂的条件表达式
categorized = ["大偶数" if x > 5 and x % 2 == 0 else 
               "小偶数" if x % 2 == 0 else 
               "大奇数" if x > 5 else 
               "小奇数" for x in range(10)]
print(categorized)

四、推导式对比传统循环

4.1 性能比较

推导式通常比等效的循环更快,因为它们在底层使用了优化的C代码。

python 复制代码
import timeit
# 测试列表推导式性能
list_comp_time = timeit.timeit('[x**2 for x in range(1000)]', number=10000)
loop_time = timeit.timeit('''
result = []
for x in range(1000):
    result.append(x**2)
''', number=10000)

print(f"列表推导式: {list_comp_time:.3f}秒")
print(f"传统循环: {loop_time:.3f}秒")

4.2 可读性比较

虽然推导式更简洁,但过度复杂的推导式可能会降低可读性:

python 复制代码
# 可读性好的推导式
good_example = [x**2 for x in range(10) if x % 2 == 0]

# 过于复杂的推导式(不推荐)
bad_example = [[x*y for y in range(10) if y % 2 == 0] for x in range(10) if x % 3 == 0]

建议:当推导式变得复杂难以理解时,考虑使用传统的循环结构。

五、常见应用场景

5.1 数据清洗和转换

python 复制代码
# 从字符串中提取数字并转换为整数
data = ["价格: 100元", "重量: 2.5kg", "数量: 15个"]
numbers = [float(''.join(filter(str.isdigit, item))) for item in data]
print(numbers)  # [100.0, 25.0, 15.0]

5.2 文件处理

python 复制代码
# 读取文件并处理行
with open('data.txt', 'r') as file:
    lines = [line.strip().upper() for line in file if line.strip()]

5.3 API数据处理

python 复制代码
# 从API响应中提取特定信息
api_response = [
    {'name': 'Alice', 'age': 25, 'active': True},
    {'name': 'Bob', 'age': 30, 'active': False},
    {'name': 'Charlie', 'age': 35, 'active': True}
]

active_users = [user['name'] for user in api_response if user['active']]
print(active_users)  # ['Alice', 'Charlie']

六、注意事项

  • 避免过度复杂:如果推导式变得难以阅读,考虑使用传统循环

  • 注意内存使用:大型数据集考虑使用生成器表达式

  • 保持可读性:适当的空格和换行可以提高复杂推导式的可读性

  • 不要滥用:推导式不是所有循环的替代品,选择合适的工具

python 复制代码
# 可读性更好的复杂推导式
result = [
    (x, y, z)
    for x in range(10)
    for y in range(10)
    for z in range(10)
    if x + y + z > 15
    and x % 2 == 0
    and y % 2 != 0
]

print(result)

参考