Skip to content

05-推导式

本章代码基于 Python 3.11+ 编写

推导式是 Python 的特色语法,用简洁的方式创建序列,提高代码可读性和性能。


本章全面讲解 Python 的列表推导式、字典推导式、集合推导式和生成器表达式。


概念铺垫

为什么需要推导式?一个高效数据转换场景

问题场景: 你需要从一个数字列表中筛选出所有偶数并计算平方。

不使用推导式的方案(循环):

python
# 传统循环方式
numbers: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result: list[int] = []

for n in numbers:
    if n % 2 == 0:  # 筛选偶数
        result.append(n ** 2)  # 计算平方

print(result)  # 输出:[4, 16, 36, 64, 100]

问题:

  • 代码较长(4行)
  • 需要先创建空列表

使用推导式的解决方案:

python
# 列表推导式(一行搞定)
numbers: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result: list[int] = [n ** 2 for n in numbers if n % 2 == 0]

print(result)  # 输出:[4, 16, 36, 64, 100]

这就是推导式的价值:简洁高效地转换数据


推导式解决了什么问题?

推导式的本质是:用声明式语法创建序列

就像你说"我要所有偶数的平方",而不是"遍历、判断、添加"。Python 帮你完成细节。

推导式的优势:

  1. 代码简洁:一行代码完成循环
  2. 可读性好:逻辑集中,意图明确
  3. 性能更好:比普通循环更快(底层优化)
  4. 函数式风格:声明式编程

L1 理解层:会用

推导式的最简用法(3分钟上手)

最常见的列表推导式:

python
# 基础列表推导式
squares: list[int] = [x ** 2 for x in range(5)]
print(squares)  # [0, 1, 4, 9, 16]

# 带条件的列表推导式
evens: list[int] = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

# 字典推导式
squares_dict: dict[int, int] = {x: x ** 2 for x in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

这就是推导式的基本用法。接下来我们详细学习各类推导式。


第一部分:推导式基础

什么是推导式

推导式(Comprehension) 是 Python 特有的一种简洁的序列生成方式,用一行代码完成循环和条件过滤。

┌─────────────────────────────────────────────────────────────┐
│                    推导式的优势                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ✅ 代码简洁:一行代码完成循环                              │
│   ✅ 可读性好:逻辑集中,意图明确                            │
│   ✅ 性能更好:比普通循环更快(底层优化)                    │
│   ✅ 函数式风格:声明式编程                                  │
│                                                             │
│   推导式类型:                                               │
│   • 列表推导式:[x for x in iterable]                       │
│   • 字典推导式:{k: v for k, v in iterable}                 │
│   • 集合推导式:{x for x in iterable}                       │
│   • 生成器表达式:(x for x in iterable)                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

推导式 vs 传统循环

python
# 传统循环
squares = []
for i in range(1, 6):
    squares.append(i ** 2)
print(squares)  # [1, 4, 9, 16, 25]

# 列表推导式
squares = [i ** 2 for i in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

# 性能对比
import timeit

def traditional_loop():
    result = []
    for i in range(1000):
        result.append(i ** 2)
    return result

def comprehension():
    return [i ** 2 for i in range(1000)]

print(timeit.timeit(traditional_loop, number=10000))
print(timeit.timeit(comprehension, number=10000))
# 推导式通常快 10-20%

第二部分:列表推导式

基本语法

列表推导式: 用一行代码创建列表,替代传统循环。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  列表推导式语法                                               │
│                                                              │
│  [表达式 for 变量 in 可迭代对象]                              │
│   ↑      ↑    ↑      ↑                                      │
│   结果   遍历  每项    数据源                                 │
│                                                              │
│  执行流程:                                                   │
│  ┌──────────────────────────────────────────┐               │
│  │ for 变量 in 可迭代对象                    │               │
│  │     ↓                                    │               │
│  │ 表达式 → 结果加入列表                     │               │
│  │     ↓                                    │               │
│  │ 继续下一个元素...                         │               │
│  └──────────────────────────────────────────┘               │
│                                                              │
│  示例:[x ** 2 for x in range(5)]                            │
│        ↓      ↓    ↓                                         │
│        平方   变量  数字0-4                                   │
│                                                              │
│  结果:[0, 1, 4, 9, 16]                                      │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 创建平方列表
squares = [i ** 2 for i in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

关键代码解释

代码含义执行过程
i ** 2表达式,计算平方对每个 i 计算平方值
for i in range(1, 6)循环部分遍历 1, 2, 3, 4, 5
[]列表容器收集所有结果

详细示例

python
# 字符串转大写
words = ["hello", "world", "python"]
upper_words = [word.upper() for word in words]
print(upper_words)  # ['HELLO', 'WORLD', 'PYTHON']

# 提取属性
persons = [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]
names = [p["name"] for p in persons]
print(names)  # ['Alice', 'Bob']

带条件的推导式

条件过滤: 在推导式末尾添加 if 条件,只保留满足条件的元素。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  带条件的列表推导式                                           │
│                                                              │
│  [表达式 for 变量 in 可迭代对象 if 条件]                      │
│   ↑      ↑    ↑      ↑        ↑                             │
│   结果   遍历  每项    数据源   过滤                          │
│                                                              │
│  执行流程:                                                   │
│  ┌──────────────────────────────────────────┐               │
│  │ for 变量 in 可迭代对象                    │               │
│  │     ↓                                    │               │
│  │ if 条件 → True: 表达式 → 加入列表        │               │
│  │         → False: 跳过                    │               │
│  └──────────────────────────────────────────┘               │
│                                                              │
│  示例:[x for x in range(10) if x % 2 == 0]                  │
│                    ↑             ↑                           │
│                    数据源         奇数过滤                    │
│                                                              │
│  结果:[0, 2, 4, 6, 8](只保留偶数)                          │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 只保留偶数
evens = [n for n in range(1, 11) if n % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

关键代码解释

代码含义执行过程
if n % 2 == 0条件判断只保留偶数
n表达式条件满足时保留原值
执行顺序先循环 → 后判断 → 再收集条件在循环之后

详细示例

python
# 筛选并处理
even_squares = [n ** 2 for n in range(1, 11) if n % 2 == 0]
print(even_squares)  # [4, 16, 36, 64, 100]

# 过滤字符串
words = ["apple", "", "banana", "", "cherry"]
non_empty = [w for w in words if w]  # 空字符串为 False
print(non_empty)  # ['apple', 'banana', 'cherry']

# 复杂条件
numbers = range(-5, 6)
positive_evens = [n for n in numbers if n > 0 and n % 2 == 0]
print(positive_evens)  # [2, 4]

条件表达式(if-else)

条件表达式: 不是过滤,而是根据条件选择不同的值。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  条件表达式(三元运算)                                        │
│                                                              │
│  [表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]        │
│   ↑      ↑        ↑                                          │
│   选择   条件    备选                                         │
│                                                              │
│  ⚠️ 注意区别:                                                │
│  ─────────────────────────────────────                       │
│  过滤:if 在末尾 → 不满足条件的元素被跳过                     │
│  选择:if-else 在表达式位置 → 每个元素都保留,值不同          │
│                                                              │
│  示例对比:                                                   │
│  [x for x in range(5) if x % 2 == 0]      → [0, 2, 4]       │
│  ["偶" if x % 2 == 0 else "奇" for x in range(5)]           │
│                                           → ['偶', '奇',...]│
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 奇偶分类(每个元素都保留)
numbers = range(1, 6)
labels = ["偶" if n % 2 == 0 else "奇" for n in numbers]
print(labels)  # ['奇', '偶', '奇', '偶', '奇']

关键代码解释

代码含义区别
if 在末尾过滤不满足条件的元素跳过
if-else 在表达式位置选择每个元素都保留,值不同

详细示例

python
# 正负分类
numbers = [-3, -1, 0, 2, 4]
categories = ["负数" if n < 0 else "零" if n == 0 else "正数" for n in numbers]
print(categories)  # ['负数', '负数', '零', '正数', '正数']

# 处理缺失值
data = [1, None, 2, None, 3]
cleaned = [x if x is not None else 0 for x in data]
print(cleaned)  # [1, 0, 2, 0, 3]

嵌套循环

嵌套推导式: 多层 for 循环,展开嵌套结构或生成组合。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  嵌套循环推导式                                               │
│                                                              │
│  [表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2]   │
│           ↑          ↑               ↑          ↑           │
│           外层循环   外层数据         内层循环   内层数据     │
│                                                              │
│  执行顺序(重要):                                           │
│  ┌──────────────────────────────────────────┐               │
│  │ for 变量1 in 可迭代对象1  ← 外层          │               │
│  │     ↓                                    │               │
│  │ for 变量2 in 可迭代对象2  ← 内层          │               │
│  │     ↓                                    │               │
│  │ 表达式 → 加入列表                         │               │
│  └──────────────────────────────────────────┘               │
│                                                              │
│  ⚠️ 注意:for 的顺序 = 传统循环的顺序                         │
│                                                              │
│  示例:[(x, y) for x in [1,2] for y in ['a','b']]            │
│  结果:[(1,'a'), (1,'b'), (2,'a'), (2,'b')]                  │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 生成所有组合
colors = ["red", "green"]
sizes = ["S", "M", "L"]
products = [(color, size) for color in colors for size in sizes]
print(products)
# [('red', 'S'), ('red', 'M'), ('red', 'L'), 
#  ('green', 'S'), ('green', 'M'), ('green', 'L')]

关键代码解释

代码含义执行顺序
for color in colors外层循环先遍历 colors
for size in sizes内层循环对每个 color 遍历 sizes
(color, size)表达式组合为元组

等价传统循环:

python
# 推导式写法
products = [(color, size) for color in colors for size in sizes]

# 传统循环写法(顺序相同)
products = []
for color in colors:          # 外层
    for size in sizes:        # 内层
        products.append((color, size))

详细示例

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]

# 带条件的嵌套循环
evens = [num for row in matrix for num in row if num % 2 == 0]
print(evens)  # [2, 4, 6, 8]

多变量解包

python
# 解包形式
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]

# 解包
result = [f"{num}:{letter}" for num, letter in pairs]
print(result)  # ['1:a', '2:b', '3:c']

# 示例:字典项解包
person = {"name": "Alice", "age": 25, "city": "Beijing"}
items = [f"{k}={v}" for k, v in person.items()]
print(items)  # ['name=Alice', 'age=25', 'city=Beijing']

# 示例:enumerate 解包
words = ["apple", "banana", "cherry"]
indexed = [f"{i}: {word}" for i, word in enumerate(words)]
print(indexed)  # ['0: apple', '1: banana', '2: cherry']

第三部分:字典推导式

基本语法

字典推导式: 用一行代码创建字典,生成键值对映射。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  字典推导式语法                                               │
│                                                              │
│  {键表达式: 值表达式 for 变量 in 可迭代对象}                  │
│   ↑       ↑       ↑    ↑      ↑                             │
│   键      值      遍历  每项    数据源                        │
│                                                              │
│  ⚠️ 注意:使用花括号 {},不是方括号 []                        │
│                                                              │
│  示例:{x: x ** 2 for x in range(5)}                         │
│        ↑   ↑                                                 │
│        键   值                                                │
│                                                              │
│  结果:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}                        │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 创建平方字典
squares = {i: i ** 2 for i in range(1, 6)}
print(squares)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

关键代码解释

代码含义说明
{}字典容器使用花括号
i:键表达式键为 i 的值
i ** 2值表达式值为 i 的平方

详细示例

python
# 交换键值对
person = {"name": "Alice", "age": 25}
swapped = {v: k for k, v in person.items()}
print(swapped)  # {'Alice': 'name', 25: 'age'}

# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["Alice", 25, "Beijing"]
person = {k: v for k, v in zip(keys, values)}
print(person)  # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}

带条件的字典推导式

python
# 示例:只保留值大于 60 的项
scores = {"Alice": 85, "Bob": 60, "Charlie": 45, "David": 92}
passed = {name: score for name, score in scores.items() if score >= 60}
print(passed)  # {'Alice': 85, 'Bob': 60, 'David': 92}

# 示例:过滤键
data = {"a": 1, "B": 2, "c": 3, "D": 4}
lowercase_keys = {k: v for k, v in data.items() if k.islower()}
print(lowercase_keys)  # {'a': 1, 'c': 3}

# 示例:处理值
prices = {"apple": 100, "banana": 50, "cherry": 200}
discounted = {fruit: price * 0.9 for fruit, price in prices.items()}
print(discounted)  # {'apple': 90.0, 'banana': 45.0, 'cherry': 180.0}

实际应用

python
# 统计字符频率
text = "hello world"
char_count = {char: text.count(char) for char in set(text)}
print(char_count)  # {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

# 分组
students = [
    {"name": "Alice", "grade": "A"},
    {"name": "Bob", "grade": "B"},
    {"name": "Charlie", "grade": "A"},
    {"name": "David", "grade": "C"}
]

# 按成绩分组
from collections import defaultdict
grades = defaultdict(list)
for s in students:
    grades[s["grade"]].append(s["name"])
print(dict(grades))  # {'A': ['Alice', 'Charlie'], 'B': ['Bob'], 'C': ['David'}

# 创建映射字典
words = ["apple", "banana", "cherry"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)  # {'apple': 5, 'banana': 6, 'cherry': 6}

第四部分:集合推导式

基本语法

集合推导式: 用一行代码创建集合,自动去重。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  集合推导式语法                                               │
│                                                              │
│  {表达式 for 变量 in 可迭代对象}                              │
│   ↑      ↑    ↑      ↑                                      │
│   元素   遍历  每项    数据源                                 │
│                                                              │
│  ⚠️ 注意:                                                   │
│  • 使用花括号 {}                                             │
│  • 自动去重(集合特性)                                       │
│  • 结果无序(集合特性)                                       │
│                                                              │
│  示例:{x ** 2 for x in [-2, -1, 0, 1, 2]}                   │
│                                                              │
│  结果:{0, 1, 4}(-2和2的平方相同,自动去重)                  │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 创建平方集合(自动去重)
squares = {i ** 2 for i in range(-2, 3)}
print(squares)  # {0, 1, 4}(-2²=4 和 2²=4 合并为一个)

关键代码解释

代码含义说明
{}集合容器使用花括号(同字典)
自动去重集合特性相同元素只保留一个
无序集合特性不保证顺序

详细示例

python
# 列表去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = {n for n in numbers}
print(unique)  # {1, 2, 3, 4}

# 字符串去重
text = "hello world"
unique_chars = {char for char in text}
print(unique_chars)  # {'h', 'e', 'l', 'o', ' ', 'w', 'r', 'd'}

带条件的集合推导式

python
# 筛选偶数
numbers = range(1, 11)
even_squares = {n ** 2 for n in numbers if n % 2 == 0}
print(even_squares)  # {64, 4, 36, 16, 100}(顺序可能不同)

# 筛选元音
text = "Hello World"
vowels = {char.lower() for char in text if char.lower() in "aeiou"}
print(vowels)  # {'e', 'o'}

# 提取唯一首字母
words = ["apple", "apricot", "banana", "cherry", "blueberry"]
first_letters = {word[0] for word in words}
print(first_letters)  # {'a', 'b', 'c'}

第五部分:生成器表达式

什么是生成器表达式

生成器表达式: 类似列表推导式,但返回生成器对象,惰性计算,节省内存。

语法结构:
┌─────────────────────────────────────────────────────────────┐
│  生成器表达式语法                                             │
│                                                              │
│  (表达式 for 变量 in 可迭代对象)                              │
│   ↑      ↑    ↑      ↑                                      │
│   结果   遍历  每项    数据源                                 │
│                                                              │
│  ⚠️ 注意:                                                   │
│  • 使用圆括号 (),不是方括号 []                               │
│  • 返回生成器对象,不是列表                                   │
│  • 惰性计算:按需生成,不预先计算                             │
│  • 只能遍历一次                                               │
│                                                              │
│  示例:(x ** 2 for x in range(5))                            │
│                                                              │
│  返回:<generator object>(生成器对象)                       │
└─────────────────────────────────────────────────────────────┘
列表推导式 vs 生成器表达式:
┌─────────────────────────────────────────────────────────────┐
│              列表推导式 vs 生成器表达式                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   列表推导式:[x for x in iterable]                         │
│   • 立即计算所有元素                                        │
│   • 返回列表                                                │
│   • 占用内存存储所有元素                                    │
│                                                             │
│   生成器表达式:(x for x in iterable)                       │
│   • 惰性计算,按需生成                                      │
│   • 返回生成器对象                                          │
│   • 内存高效,不存储所有元素                                │
│                                                             │
│   选择建议:                                                 │
│   • 需要多次遍历 → 列表推导式                               │
│   • 只遍历一次 → 生成器表达式                               │
│   • 数据量大 → 生成器表达式                                 │
│   • 需要索引访问 → 列表推导式                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

最简示例

python
# 列表推导式
squares_list = [i ** 2 for i in range(5)]
print(squares_list)  # [0, 1, 4, 9, 16]
print(type(squares_list))  # <class 'list'>

# 生成器表达式
squares_gen = (i ** 2 for i in range(5))
print(squares_gen)  # <generator object <genexpr> at 0x...>
print(type(squares_gen))  # <class 'generator'>

关键代码解释

代码含义说明
()圆括号生成器表达式语法
惰性计算不预先计算遍历时才计算
只遍历一次生成器特性耗尽后无法再次遍历

详细示例

python
# 遍历生成器
squares_gen = (i ** 2 for i in range(5))
for square in squares_gen:
    print(square)  # 0, 1, 4, 9, 16

# 生成器只能遍历一次
squares_gen = (i ** 2 for i in range(3))
print(list(squares_gen))  # [0, 1, 4]
print(list(squares_gen))  # [](已耗尽!)

内存优势

python
import sys

# 列表推导式:占用大量内存
big_list = [i ** 2 for i in range(1000000)]
print(f"列表内存: {sys.getsizeof(big_list)} 字节")  # 约 8MB

# 生成器表达式:内存占用极小
big_gen = (i ** 2 for i in range(1000000))
print(f"生成器内存: {sys.getsizeof(big_gen)} 字节")  # 约 100 字节

# 生成器不存储所有元素,只存储当前状态

关键代码解释:

方式内存占用原因
列表推导式大(8MB)存储 100万个元素
生成器表达式小(100字节)只存储当前状态,按需计算

与函数配合

python
# 与 sum() 配合
total = sum(i ** 2 for i in range(100))
print(total)  # 328350

# 与 max()/min() 配合
data = [1, -2, 3, -4, 5]
max_abs = max(abs(x) for x in data)
print(max_abs)  # 5

# 与 any()/all() 配合
numbers = [2, 4, 6, 8, 10]
has_odd = any(n % 2 != 0 for n in numbers)
print(has_odd)  # False
all_positive = all(n > 0 for n in numbers)
print(all_positive)  # True

# 与 join() 配合
words = ["hello", "world"]
result = " ".join(word.upper() for word in words)
print(result)  # "HELLO WORLD"

# 与 sorted() 配合
students = [("Alice", 85), ("Bob", 90), ("Charlie", 78)]
sorted_by_score = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_by_score)

带条件的生成器表达式

python
# 筛选偶数
evens = (n for n in range(100) if n % 2 == 0)
print(list(evens)[:10])  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# 处理文件行
# 假设有一个大文件
# lines = (line.strip() for line in open('large_file.txt') if line.strip())

# 链式处理
numbers = range(100)
result = (n ** 2 for n in numbers if n % 2 == 0)
result = (n for n in result if n < 1000)
print(list(result))  # [0, 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900]

带条件的推导式

python
# 带条件的形式
# [表达式 for 变量 in 可迭代对象 if 条件]

# 示例:只保留偶数
evens = [n for n in range(1, 11) if n % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

# 示例:筛选并处理
even_squares = [n ** 2 for n in range(1, 11) if n % 2 == 0]
print(even_squares)  # [4, 16, 36, 64, 100]

# 示例:过滤字符串
words = ["apple", "", "banana", "", "cherry"]
non_empty = [w for w in words if w]
print(non_empty)  # ['apple', 'banana', 'cherry']

# 示例:复杂条件
numbers = range(-5, 6)
positive_evens = [n for n in numbers if n > 0 and n % 2 == 0]
print(positive_evens)  # [2, 4]

条件表达式

python
# if-else 表达式(不是过滤,是选择)
# [表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]

# 示例:奇偶分类
numbers = range(1, 6)
labels = ["偶" if n % 2 == 0 else "奇" for n in numbers]
print(labels)  # ['奇', '偶', '奇', '偶', '奇']

# 示例:正负分类
numbers = [-3, -1, 0, 2, 4]
categories = ["负数" if n < 0 else "零" if n == 0 else "正数" for n in numbers]
print(categories)  # ['负数', '负数', '零', '正数', '正数']

# 示例:处理缺失值
data = [1, None, 2, None, 3]
cleaned = [x if x is not None else 0 for x in data]
print(cleaned)  # [1, 0, 2, 0, 3]

嵌套循环

python
# 嵌套循环形式
# [表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2]

# 示例:生成所有组合
colors = ["red", "green"]
sizes = ["S", "M", "L"]
products = [(color, size) for color in colors for size in sizes]
print(products)
# [('red', 'S'), ('red', 'M'), ('red', 'L'), 
#  ('green', 'S'), ('green', 'M'), ('green', 'L')]

# 示例:展开嵌套列表
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]

# 等价于传统循环
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)

# 示例:带条件的嵌套循环
# 找出所有偶数
evens = [num for row in matrix for num in row if num % 2 == 0]
print(evens)  # [2, 4, 6, 8]

多变量解包

python
# 解包形式
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]

# 解包
result = [f"{num}:{letter}" for num, letter in pairs]
print(result)  # ['1:a', '2:b', '3:c']

# 示例:字典项解包
person = {"name": "Alice", "age": 25, "city": "Beijing"}
items = [f"{k}={v}" for k, v in person.items()]
print(items)  # ['name=Alice', 'age=25', 'city=Beijing']

# 示例:enumerate 解包
words = ["apple", "banana", "cherry"]
indexed = [f"{i}: {word}" for i, word in enumerate(words)]
print(indexed)  # ['0: apple', '1: banana', '2: cherry']

第三部分:字典推导式

基本语法

python
# 基本形式
# {键表达式: 值表达式 for 变量 in 可迭代对象}

# 示例:创建平方字典
squares = {i: i ** 2 for i in range(1, 6)}
print(squares)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 示例:交换键值对
person = {"name": "Alice", "age": 25}
swapped = {v: k for k, v in person.items()}
print(swapped)  # {'Alice': 'name', 25: 'age'}

# 示例:从两个列表创建字典
keys = ["name", "age", "city"]
values = ["Alice", 25, "Beijing"]
person = {k: v for k, v in zip(keys, values)}
print(person)  # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}

带条件的字典推导式

python
# 示例:只保留值大于 60 的项
scores = {"Alice": 85, "Bob": 60, "Charlie": 45, "David": 92}
passed = {name: score for name, score in scores.items() if score >= 60}
print(passed)  # {'Alice': 85, 'Bob': 60, 'David': 92}

# 示例:过滤键
data = {"a": 1, "B": 2, "c": 3, "D": 4}
lowercase_keys = {k: v for k, v in data.items() if k.islower()}
print(lowercase_keys)  # {'a': 1, 'c': 3}

# 示例:处理值
prices = {"apple": 100, "banana": 50, "cherry": 200}
discounted = {fruit: price * 0.9 for fruit, price in prices.items()}
print(discounted)  # {'apple': 90.0, 'banana': 45.0, 'cherry': 180.0}

实际应用

python
# 统计字符频率
text = "hello world"
char_count = {char: text.count(char) for char in set(text)}
print(char_count)  # {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

# 分组
students = [
    {"name": "Alice", "grade": "A"},
    {"name": "Bob", "grade": "B"},
    {"name": "Charlie", "grade": "A"},
    {"name": "David", "grade": "C"}
]

# 按成绩分组
from collections import defaultdict
grades = defaultdict(list)
for s in students:
    grades[s["grade"]].append(s["name"])
print(dict(grades))  # {'A': ['Alice', 'Charlie'], 'B': ['Bob'], 'C': ['David']}

# 创建映射字典
words = ["apple", "banana", "cherry"]
word_lengths = {word: len(word) for word in words}
print(word_lengths)  # {'apple': 5, 'banana': 6, 'cherry': 6}

第四部分:集合推导式

基本语法

python
# 基本形式
# {表达式 for 变量 in 可迭代对象}

# 示例:创建平方集合
squares = {i ** 2 for i in range(1, 6)}
print(squares)  # {1, 4, 9, 16, 25}

# 示例:自动去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique = {n for n in numbers}
print(unique)  # {1, 2, 3, 4}

# 示例:字符串去重
text = "hello world"
unique_chars = {char for char in text}
print(unique_chars)  # {'h', 'e', 'l', 'o', ' ', 'w', 'r', 'd'}

带条件的集合推导式

python
# 示例:筛选偶数
numbers = range(1, 11)
even_squares = {n ** 2 for n in numbers if n % 2 == 0}
print(even_squares)  # {64, 4, 36, 16, 100}

# 示例:筛选元音
text = "Hello World"
vowels = {char.lower() for char in text if char.lower() in "aeiou"}
print(vowels)  # {'e', 'o'}

# 示例:提取唯一首字母
words = ["apple", "apricot", "banana", "cherry", "blueberry"]
first_letters = {word[0] for word in words}
print(first_letters)  # {'a', 'b', 'c'}

第五部分:生成器表达式

什么是生成器表达式

生成器表达式 类似于列表推导式,但返回生成器对象,按需生成元素,节省内存。

┌─────────────────────────────────────────────────────────────┐
│              列表推导式 vs 生成器表达式                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   列表推导式:[x for x in iterable]                         │
│   • 立即计算所有元素                                        │
│   • 返回列表                                                │
│   • 占用内存存储所有元素                                    │
│                                                             │
│   生成器表达式:(x for x in iterable)                       │
│   • 惰性计算,按需生成                                      │
│   • 返回生成器对象                                          │
│   • 内存高效,不存储所有元素                                │
│                                                             │
│   选择建议:                                                 │
│   • 需要多次遍历 → 列表推导式                               │
│   • 只遍历一次 → 生成器表达式                               │
│   • 数据量大 → 生成器表达式                                 │
│   • 需要索引访问 → 列表推导式                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

基本用法

python
# 列表推导式
squares_list = [i ** 2 for i in range(5)]
print(squares_list)  # [0, 1, 4, 9, 16]
print(type(squares_list))  # <class 'list'>

# 生成器表达式
squares_gen = (i ** 2 for i in range(5))
print(squares_gen)  # <generator object <genexpr> at 0x...>
print(type(squares_gen))  # <class 'generator'>

# 遍历生成器
for square in squares_gen:
    print(square)

# 生成器只能遍历一次
squares_gen = (i ** 2 for i in range(3))
print(list(squares_gen))  # [0, 1, 4]
print(list(squares_gen))  # [](已耗尽)

内存优势

python
import sys

# 列表推导式:占用大量内存
big_list = [i ** 2 for i in range(1000000)]
print(f"列表内存: {sys.getsizeof(big_list)} 字节")  # 约 8MB

# 生成器表达式:内存占用极小
big_gen = (i ** 2 for i in range(1000000))
print(f"生成器内存: {sys.getsizeof(big_gen)} 字节")  # 约 100 字节

# 生成器不存储所有元素,只存储当前状态

与函数配合

python
# 与 sum() 配合
total = sum(i ** 2 for i in range(100))
print(total)  # 328350

# 与 max()/min() 配合
data = [1, -2, 3, -4, 5]
max_abs = max(abs(x) for x in data)
print(max_abs)  # 5

# 与 any()/all() 配合
numbers = [2, 4, 6, 8, 10]
has_odd = any(n % 2 != 0 for n in numbers)
print(has_odd)  # False
all_positive = all(n > 0 for n in numbers)
print(all_positive)  # True

# 与 join() 配合
words = ["hello", "world"]
result = " ".join(word.upper() for word in words)
print(result)  # "HELLO WORLD"

# 与 sorted() 配合
students = [("Alice", 85), ("Bob", 90), ("Charlie", 78)]
sorted_by_score = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_by_score)

带条件的生成器表达式

python
# 筛选偶数
evens = (n for n in range(100) if n % 2 == 0)
print(list(evens)[:10])  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# 处理文件行
# 假设有一个大文件
# lines = (line.strip() for line in open('large_file.txt') if line.strip())

# 链式处理
numbers = range(100)
result = (n ** 2 for n in numbers if n % 2 == 0)
result = (n for n in result if n < 1000)
print(list(result))  # [0, 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900]

第六部分:推导式最佳实践

可读性原则

python
# ✅ 简洁明了
squares = [i ** 2 for i in range(10)]

# ❌ 过于复杂
# result = [x for sublist in matrix for x in sublist if x > 0 if x % 2 == 0]

# ✅ 拆分为多步
flattened = [x for row in matrix for x in row]
positive = [x for x in flattened if x > 0]
even_positive = [x for x in positive if x % 2 == 0]

# ✅ 或使用传统循环
result = []
for row in matrix:
    for x in row:
        if x > 0 and x % 2 == 0:
            result.append(x)

# 经验法则:
# • 超过 2 个 for 或 if,考虑使用传统循环
# • 一行代码超过 80 字符,考虑拆分
# • 逻辑复杂时,优先可读性

性能考虑

python
import timeit

# 列表推导式 vs map()
numbers = range(1000)

# 列表推导式
squares_comp = [x ** 2 for x in numbers]

# map()
squares_map = list(map(lambda x: x ** 2, numbers))

# 性能对比
print(timeit.timeit('[x ** 2 for x in range(1000)]', number=10000))
print(timeit.timeit('list(map(lambda x: x ** 2, range(1000)))', number=10000))
# 列表推导式通常更快

# 但 map() 在某些情况下更高效
# 例如使用内置函数
print(timeit.timeit('[str(x) for x in range(1000)]', number=10000))
print(timeit.timeit('list(map(str, range(1000)))', number=10000))
# map(str, ...) 可能更快

常见错误

python
# 错误 1:变量作用域泄露(Python 3 已修复)
x = 10
result = [x for x in range(5)]
print(x)  # 10(Python 3 中不变)

# 错误 2:修改外部变量
total = 0
# [total := total + x for x in range(5)]  # 不推荐
# 使用 sum()
total = sum(range(5))

# 错误 3:生成器耗尽
gen = (x for x in range(3))
print(list(gen))  # [0, 1, 2]
print(list(gen))  # [](已耗尽)

# 错误 4:混淆 if 位置
# 过滤(if 在末尾)
evens = [x for x in range(10) if x % 2 == 0]

# 选择(if-else 在表达式位置)
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]

第七部分:推导式对比总结

┌─────────────────────────────────────────────────────────────┐
│                    推导式对比总结                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   类型          语法                    返回类型            │
│   ─────────────────────────────────────────────             │
│   列表推导式    [x for x in iter]       list               │
│   字典推导式    {k: v for ...}          dict               │
│   集合推导式    {x for x in iter}       set                │
│   生成器表达式  (x for x in iter)       generator          │
│                                                             │
│   使用场景:                                                 │
│   ─────────────────────────────────────────────             │
│   列表推导式:需要索引访问、多次遍历                        │
│   字典推导式:创建映射关系                                  │
│   集合推导式:去重、集合运算                                │
│   生成器表达式:大数据、单次遍历、内存敏感                  │
│                                                             │
│   性能特点:                                                 │
│   ─────────────────────────────────────────────             │
│   列表推导式:内存占用大,访问快                            │
│   生成器表达式:内存占用小,惰性计算                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

从简单到复杂:推导式的渐进应用

层级1:基础转换

python
# 数字平方
squares: list[int] = [x ** 2 for x in range(5)]
print(squares)  # [0, 1, 4, 9, 16]

层级2:条件过滤

python
# 筛选偶数
numbers: list[int] = list(range(10))
evens: list[int] = [x for x in numbers if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

层级3:嵌套循环

python
# 生成坐标点
points: list[tuple[int, int]] = [(x, y) for x in range(3) for y in range(3)]
print(points)  # [(0,0), (0,1), (0,2), (1,0), ...]

层级4:字典推导式

python
# 字符串长度映射
words: list[str] = ["apple", "banana", "cherry"]
word_lengths: dict[str, int] = {w: len(w) for w in words}
print(word_lengths)  # {'apple': 5, 'banana': 6, 'cherry': 6}

层级5:生成器表达式

python
# 处理大数据(惰性计算)
big_data = range(1000000)
sum_of_squares: int = sum(x ** 2 for x in big_data if x % 2 == 0)
print(sum_of_squares)

综合应用:数据处理管道

这个示例综合运用多种推导式:

python
# 数据处理管道(Python 3.11+)
from typing import Any

def process_students(students: list[dict[str, Any]]) -> dict[str, Any]:
    """
    处理学生数据
    
    Args:
        students: 学生列表
    
    Returns:
        处理结果
    """
    # 列表推导式:筛选及格学生
    passed: list[dict[str, Any]] = [
        s for s in students if s["score"] >= 60
    ]
    
    # 字典推导式:创建学号-姓名映射
    id_name_map: dict[int, str] = {
        s["id"]: s["name"] for s in students
    }
    
    # 列表推导式 + 嵌套:提取所有成绩
    all_scores: list[int] = [
        score for s in students for score in s.get("scores", [])
    ]
    
    # 集合推导式:获取唯一课程
    courses: set[str] = {s["course"] for s in students}
    
    # 生成器表达式:计算平均分
    avg_score: float = sum(s["score"] for s in students) / len(students)
    
    return {
        "passed_count": len(passed),
        "id_name_map": id_name_map,
        "all_scores": all_scores,
        "courses": courses,
        "average_score": avg_score
    }

# 使用示例
students_data: list[dict[str, Any]] = [
    {"id": 1, "name": "张三", "score": 85, "course": "数学", "scores": [80, 90, 85]},
    {"id": 2, "name": "李四", "score": 92, "course": "数学", "scores": [88, 95, 93]},
    {"id": 3, "name": "王五", "score": 58, "course": "物理", "scores": [55, 60, 59]},
]

result: dict[str, Any] = process_students(students_data)
print("=== 处理结果 ===")
print(f"及格人数:{result['passed_count']}")
print(f"平均分:{result['average_score']:.1f}")
print(f"课程:{result['courses']}")
print(f"学号映射:{result['id_name_map']}")

这个示例展示了:

  • 列表推导式筛选和转换
  • 字典推导式创建映射
  • 集合推导式去重
  • 生成器表达式惰性计算
  • 嵌套推导式提取数据
  • 类型提示的现代语法

L2 实践层:用好

最佳实践

推导式类型选择指南

场景推荐方式原因
创建列表并多次使用列表推导式可索引、可重复遍历
创建键值映射字典推导式一行创建映射
去重集合推导式自动去重
大数据处理(单次遍历)生成器表达式内存高效
与 sum/max/any 配合生成器表达式无需中间列表
需要索引访问列表推导式生成器不支持索引

反模式:不要这样做

python
# ❌ 反模式 1:推导式用于副作用
[print(x) for x in range(5)]  # 创建无用列表 [None, None, None, None, None]

# ✅ 正确做法:用 for 循环
for x in range(5):
    print(x)
python
# ❌ 反模式 2:过于复杂的嵌套
result = [x for row in matrix for x in row if x > 0 if x % 2 == 0]

# ✅ 正确做法:拆分或用传统循环
flattened = [x for row in matrix for x in row]
result = [x for x in flattened if x > 0 and x % 2 == 0]
python
# ❌ 反模式 3:生成器表达式多次遍历
gen = (x ** 2 for x in range(5))
list(gen)  # [0, 1, 4, 9, 16]
list(gen)  # [](已耗尽)

# ✅ 正确做法:用列表推导式或重新创建
lst = [x ** 2 for x in range(5)]  # 可重复遍历
python
# ❌ 反模式 4:混淆过滤 if 和选择 if-else
# 过滤(if 在末尾)- 跳过某些元素
evens = [x for x in range(10) if x % 2 == 0]  # [0, 2, 4, 6, 8]

# 选择(if-else 在表达式)- 每个元素都保留,值不同
labels = ["偶" if x % 2 == 0 else "奇" for x in range(10)]  # 10个元素
python
# ❌ 反模式 5:用推导式修改外部变量
total = 0
result = [total := total + x for x in range(5)]  # 不推荐

# ✅ 正确做法:用内置函数
total = sum(range(5))
python
# ❌ 反模式 6:忘记生成器需要函数配合时省略括号
sum([x ** 2 for x in range(100)])  # 创建临时列表

# ✅ 正确做法:直接传生成器(函数调用时括号可省)
sum(x ** 2 for x in range(100))   # 无临时列表,更高效

适用场景

场景推导式适用原因
数据转换(筛选、映射)✅ 推荐声明式,简洁
简单条件过滤✅ 推荐一行完成
嵌套遍历(≤2层)✅ 推荐比循环简洁
打印、写入文件❌ 用 for 循环推导式不应有副作用
需要异常处理❌ 用 for 循环推导式难以处理异常
嵌套超过2层❌ 用 for 循环可读性下降
需要多次遍历❌ 用列表而非生成器生成器耗尽

性能专项:生成器 vs 列表(大数据)

python
import sys, timeit

# 列表推导式:100万个元素 → 内存暴涨
big_list = [x ** 2 for x in range(1_000_000)]
print(f"列表内存: {sys.getsizeof(big_list) / 1024 / 1024:.1f} MB")  # ~8 MB

# 生成器表达式:内存几乎不变
big_gen = (x ** 2 for x in range(1_000_000))
print(f"生成器内存: {sys.getsizeof(big_gen)} bytes")  # ~100 bytes

# 与内置函数配合时的性能(省略中间括号)
# ✅ sum() + 生成器 — 无中间列表
print(timeit.timeit('sum(x ** 2 for x in range(100000))', number=100))
# ~0.5s,内存恒定

# ❌ sum() + 列表推导 — 创建完整列表
print(timeit.timeit('sum([x ** 2 for x in range(100000)])', number=100))
# ~0.6s,额外 ~800KB 内存

推导式"不该用"的场景

python
# ❌ 反模式 1:推导式用于副作用(打印、写文件)
results = [print(x) for x in range(5)]  # 创建无用列表 [None, None, ...]
# ✅ 正确
for x in range(5):
    print(x)

# ❌ 反模式 2:嵌套超过 2 层 — 可读性崩溃
matrix = [[[i+j+k for k in range(3)] for j in range(3)] for i in range(3)]
# ✅ 正确:拆分或使用传统循环
matrix = []
for i in range(3):
    row = []
    for j in range(3):
        row.append([i+j+k for k in range(3)])
    matrix.append(row)

# ❌ 反模式 3:推导式中 raise 或 try-except
# [x / y for x, y in zip(a, b)]  # y=0 → ZeroDivisionError,推导式无法处理
# ✅ 正确
def safe_div(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return float('inf')

results = [safe_div(x, y) for x, y in zip(a, b)]

# ❌ 反模式 4:推导式内修改外部变量(海象运算符滥用)
total = 0
[r := total := total + x for x in range(5)]  # 可运行但不推荐
# ✅ 正确:使用内置函数
total = sum(range(5))

L3 专家层:深入

底层原理:字节码优化

Python 如何优化推导式

列表推导式在 Python 3 中有专门的字节码指令,比普通循环更高效:

推导式 vs 循环字节码:
┌─────────────────────────────────────────────────────────────┐
│                    字节码对比                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   列表推导式 [x ** 2 for x in range(5)]                      │
│   ─────────────────────────────────────                      │
│   • BUILD_LIST              创建空列表                       │
│   • GET_ITER                获取迭代器                       │
│   • FOR_ITER + JUMP         循环迭代                         │
│   • STORE_FAST              存储变量                         │
│   • BINARY_POWER            计算平方                         │
│   • LIST_APPEND             添加到列表(优化的!)            │
│                                                             │
│   普通循环                                                    │
│   ─────────────────────────────────────                      │
│   • BUILD_LIST              创建空列表                       │
│   • LOAD_GLOBAL 'range'     加载函数                         │
│   • CALL_FUNCTION           调用                             │
│   • GET_ITER                获取迭代器                       │
│   • FOR_ITER + JUMP         循环迭代                         │
│   • LOAD_FAST 'x'           加载变量                         │
│   • BINARY_POWER            计算平方                         │
│   • LOAD_FAST 'result'      加载列表                         │
│   • LOAD_METHOD 'append'    加载方法                         │
│   • CALL_METHOD             调用 append(慢!)              │
│   • POP_TOP                 清理                             │
│                                                             │
│   关键区别:                                                  │
│   ─────────────────────────────────────                      │
│   • LIST_APPEND 比 CALL_METHOD 'append' 快                   │
│   • 推导式少几条字节码                                        │
│   • 推导式有专用优化                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

查看字节码

python
import dis

# 推导式字节码
dis.dis("[x ** 2 for x in range(5)]")

# 普通循环字节码
def loop():
    result = []
    for x in range(5):
        result.append(x ** 2)
    return result

dis.dis(loop)

性能考量

python
import timeit

# 推导式 vs 循环
comp_time = timeit.timeit('[x ** 2 for x in range(1000)]', number=10000)
# ~0.3s

loop_time = timeit.timeit('''
result = []
for x in range(1000):
    result.append(x ** 2)
''', number=10000)
# ~0.5s(慢 60%+)

# 生成器 vs 列表内存
import sys
lst = [x ** 2 for x in range(100000)]
gen = (x ** 2 for x in range(100000))

print(f"列表: {sys.getsizeof(lst)} bytes")  # ~800KB
print(f"生成器: {sys.getsizeof(gen)} bytes")  # ~100 bytes
方式速度内存说明
列表推导式字节码优化,预分配
普通循环较慢append 方法调用开销
生成器表达式最快创建最小不存储,按需生成
map + lambda中等比推导式稍慢

设计动机

设计选择原因影响
专用字节码 LIST_APPEND性能优化比 append 快
惰性生成器大数据场景节省内存
独立作用域(Python 3)防止变量泄露推导式变量不影响外部
简洁语法可读性声明式风格

知识关联

推导式知识关联图:
                    ┌─────────────────┐
                    │   可迭代对象    │
                    │  iterable       │
                    └─────────────────┘

           ┌───────────────┼───────────────┐
           │               │               │
           ▼               ▼               ▼
    ┌───────────┐   ┌───────────┐   ┌───────────┐
    │ 列表推导式│   │ 字典推导式│   │ 集合推导式│
    │   [x]     │   │   {k:v}   │   │   {x}     │
    │ 立即创建  │   │ 键值映射  │   │ 唯一元素  │
    └───────────┘   └───────────┘   └───────────┘

           │ 惰性版本

    ┌───────────┐
    │ 生成器表达式│
    │   (x)      │
    │ 惰性计算   │
    │ 节省内存   │
    └───────────┘

           │ 进阶

    ┌───────────┐
    │ 生成器函数 │
    │   yield   │
    │ 更复杂逻辑 │
    └───────────┘

对比:
    推导式 ──→ 简洁、声明式 ──→ 适合简单场景
    for循环 ──→ 灵活 ──→ 适合复杂逻辑/异常处理
    map ──→ 函数式 ──→ 内置函数时更快

综合性能基准测试

python
import timeit
import sys

n = 100_000

# 1. 列表推导 vs for 循环 vs map
print("=== 创建平方列表 ===")
print(f"列表推导: {timeit.timeit('[x**2 for x in range(1000)]', number=1000):.4f}s")
print(f"for循环:  {timeit.timeit('r=[]\nfor x in range(1000): r.append(x**2)', number=1000):.4f}s")
print(f"map():    {timeit.timeit('list(map(lambda x:x**2, range(1000)))', number=1000):.4f}s")

# 2. 内存对比:列表 vs 生成器
lst = [x ** 2 for x in range(n)]
gen = (x ** 2 for x in range(n))
print(f"\n列表内存 (n={n}): {sys.getsizeof(lst) / 1024:.0f} KB")
print(f"生成器内存 (n={n}): {sys.getsizeof(gen)} bytes")

# 3. 带过滤推导 vs filter
print(f"\n=== 过滤偶数 ===")
print(f"推导+if:  {timeit.timeit('[x for x in range(10000) if x%2==0]', number=1000):.4f}s")
print(f"filter:   {timeit.timeit('list(filter(lambda x:x%2==0, range(10000)))', number=1000):.4f}s")

# 4. 字典推导 vs 传统循环
print(f"\n=== 创建键值映射 ===")
print(f"字典推导: {timeit.timeit('{x:x**2 for x in range(1000)}', number=1000):.4f}s")
print(f"for循环:  {timeit.timeit('d={}\nfor x in range(1000): d[x]=x**2', number=1000):.4f}s")

# 5. 生成器表达式与 sum 配合
print(f"\n=== sum() 配合 ===")
print(f"生成器: {timeit.timeit('sum(x**2 for x in range(100000))', number=100):.4f}s")
print(f"列表:   {timeit.timeit('sum([x**2 for x in range(100000)])', number=100):.4f}s")
场景最快方式比最慢快
创建平方列表 (n=1000)列表推导比 map ~30%
过滤偶数 (n=10000)推导+if比 filter ~50%
键值映射 (n=1000)字典推导比 for ~40%
sum + 大数据 (n=100k)生成器省 ~800KB 内存
内置函数 + 生成器genexpr + sum不创建中间列表

本章小结

┌─────────────────────────────────────────────────────────────┐
│                    推导式 知识要点                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   列表推导式:                                               │
│   ✓ [表达式 for 变量 in 可迭代对象]                         │
│   ✓ [表达式 for 变量 in 可迭代对象 if 条件]                 │
│   ✓ [表达式 for 变量1 in iter1 for 变量2 in iter2]          │
│                                                             │
│   字典推导式:                                               │
│   ✓ {键: 值 for 变量 in 可迭代对象}                         │
│   ✓ {键: 值 for 变量 in 可迭代对象 if 条件}                 │
│                                                             │
│   集合推导式:                                               │
│   ✓ {表达式 for 变量 in 可迭代对象}                         │
│                                                             │
│   生成器表达式:                                             │
│   ✓ (表达式 for 变量 in 可迭代对象)                         │
│   ✓ 惰性计算、内存高效                                      │
│   ✓ 只能遍历一次                                            │
│                                                             │
│   最佳实践:                                                 │
│   ✓ 保持简洁,超过 2 个条件考虑传统循环                     │
│   ✓ 大数据用生成器表达式                                    │
│   ✓ 需要多次遍历用列表推导式                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘