显示页面讨论过去修订反向链接回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== 第六章:推导式与生成器表达式 ====== ===== 本章目标 ===== 完成本章学习后,你将能够: * 熟练使用列表推导式、字典推导式、集合推导式 * 理解生成器表达式的原理和用法 * 掌握嵌套推导式 * 理解推导式与循环的性能差异 * 在合适的场景选择最佳实现方式 ===== 列表推导式 ===== ==== 基本语法 ==== <code 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] </code> 语法:'[expression for item in iterable]' ==== 带条件的列表推导式 ==== <code python> # 只保留偶数 evens = [x for x in range(20) if x % 2 == 0] print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] # 处理符合条件的元素 double_evens = [x * 2 for x in range(20) if x % 2 == 0] print(double_evens) # [0, 4, 8, 12, 16, 20, 24, 28, 32, 36] # if-else表达式 labels = ["even" if x % 2 == 0 else "odd" for x in range(10)] print(labels) # ['even', 'odd', 'even', 'odd', ...] </code> ==== 嵌套列表推导式 ==== <code python> # 矩阵转置 matrix = [ [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]] # 扁平化矩阵 flattened = [x for row in matrix for x in row] print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 组合两个列表 combinations = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y] print(combinations) # [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), ...] </code> ===== 字典推导式 ===== ==== 基本语法 ==== <code python> # 创建平方数字典 squares = {x: x ** 2 for x in range(10)} print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, ...} # 从两个列表创建字典 keys = ['a', 'b', 'c'] values = [1, 2, 3] d = {k: v for k, v in zip(keys, values)} print(d) # {'a': 1, 'b': 2, 'c': 3} </code> ==== 字典转换 ==== <code python> # 交换键值 original = {'a': 1, 'b': 2, 'c': 3} swapped = {v: k for k, v in original.items()} print(swapped) # {1: 'a', 2: 'b', 3: 'c'} # 过滤字典 scores = {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'David': 95} passed = {k: v for k, v in scores.items() if v >= 80} print(passed) # {'Alice': 85, 'Bob': 92, 'David': 95} # 转换值 prices = {'apple': 1.5, 'banana': 0.8, 'cherry': 2.5} prices_yen = {k: v * 150 for k, v in prices.items()} # 转换为日元 </code> ===== 集合推导式 ====== <code python> # 基本集合推导式 squares = {x ** 2 for x in range(20)} print(squares) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, ...} # 注意:自动去重,因为集合不允许重复 # 带条件的集合推导式 even_squares = {x ** 2 for x in range(20) if x % 2 == 0} print(even_squares) # 从字符串创建集合 unique_chars = {c.lower() for c in "Hello World!" if c.isalpha()} print(unique_chars) # {'h', 'e', 'l', 'o', 'w', 'r', 'd'} </code> ===== 生成器表达式 ===== ==== 什么是生成器 ==== 生成器是**惰性求值**的迭代器,只在需要时生成值,节省内存。 <code python> # 列表推导式 - 立即计算,占用内存 squares_list = [x ** 2 for x in range(1000000)] # 占用大量内存 # 生成器表达式 - 惰性计算,节省内存 squares_gen = (x ** 2 for x in range(1000000)) # 几乎不占用内存 print(squares_gen) # <generator object <genexpr> at 0x...> # 逐个获取值 print(next(squares_gen)) # 0 print(next(squares_gen)) # 1 print(next(squares_gen)) # 4 </code> ==== 生成器的使用 ==== <code python> # 遍历生成器 gen = (x ** 2 for x in range(10)) for value in gen: print(value) # 转换为列表(会消耗生成器) gen = (x ** 2 for x in range(10)) print(list(gen)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] # print(list(gen)) # [],生成器已耗尽 # 生成器只能遍历一次 gen = (x for x in range(5)) print(sum(gen)) # 10 print(sum(gen)) # 0,生成器已耗尽 </code> ==== 生成器的优势 ==== <code python> import sys # 内存占用对比 list_comp = [x * 2 for x in range(10000)] gen_expr = (x * 2 for x in range(10000)) print(f"列表推导式: {sys.getsizeof(list_comp)} bytes") print(f"生成器表达式: {sys.getsizeof(gen_expr)} bytes") # 处理大数据集 # 假设我们有一个大文件 def process_lines(filename): # 生成器逐行读取,不占用大量内存 return (line.strip().upper() for line in open(filename)) # 查找包含特定词的行 def find_lines(filename, word): return (line for line in open(filename) if word in line) </code> ===== 推导式高级技巧 ===== ==== 复杂条件 ==== <code python> # 多条件筛选 numbers = range(100) result = [x for x in numbers if x % 2 == 0 if x % 3 == 0] # 等效于:if x % 2 == 0 and x % 3 == 0 print(result) # [0, 6, 12, 18, ...] # 嵌套if-else grades = [85, 92, 78, 65, 55, 95] categories = [ "优秀" if g >= 90 else "良好" if g >= 80 else "中等" if g >= 70 else "及格" if g >= 60 else "不及格" for g in grades ] </code> ==== 与函数结合 ==== <code python> # 在推导式中调用函数 def process(x): return x ** 2 + 1 results = [process(x) for x in range(10)] # 嵌套函数调用 words = ["hello", "WORLD", "PyThOn"] normalized = [word.strip().lower().capitalize() for word in words] print(normalized) # ['Hello', 'World', 'Python'] </code> ===== 性能比较 ===== <code python> import timeit # 性能测试 list_time = timeit.timeit('[x**2 for x in range(1000)]', number=1000) loop_time = timeit.timeit(''' result = [] for x in range(1000): result.append(x**2) ''', number=1000) map_time = timeit.timeit('list(map(lambda x: x**2, range(1000)))', number=1000) print(f"列表推导式: {list_time:.4f}s") print(f"for循环: {loop_time:.4f}s") print(f"map函数: {map_time:.4f}s") </code> 通常:列表推导式 ≈ map > for循环(列表推导式往往更快且更易读) ===== 何时使用推导式 ===== ==== 使用推导式的情况 ==== * 简单的转换和过滤 * 代码简洁且易读 * 结果需要全部存储在内存中(列表)或惰性计算(生成器) <code python> # 好的使用场景 squares = [x**2 for x in range(100)] evens = [x for x in items if x % 2 == 0] char_freq = {c: text.count(c) for c in set(text)} </code> ==== 避免使用推导式的情况 ==== * 逻辑过于复杂 * 需要副作用(如打印、修改外部变量) * 需要多行注释说明 <code python> # 避免:过于复杂的推导式 result = [f(x) if x > 0 else g(x) if x < 0 else h(x) for x in items if x not in excluded] # 更好:使用普通循环 result = [] for x in items: if x in excluded: continue if x > 0: result.append(f(x)) elif x < 0: result.append(g(x)) else: result.append(h(x)) </code> ===== 本章练习 ===== 1. **列表推导式练习**:使用一行代码生成1到100中能被3或5整除的数的平方 2. **字典转换**:给定一个字符串列表,创建字典{单词: 长度} 3. **集合去重**:给定嵌套列表[[1,2,2], [3,3,4], [1,2]],获取所有唯一元素 4. **生成器实战**:创建一个生成器产生斐波那契数列 5. **矩阵操作**:使用嵌套推导式实现矩阵乘法 ===== 本章小结 ===== 本章我们学习了: * 列表、字典、集合推导式的语法 * 嵌套推导式的使用 * 生成器表达式的惰性求值特性 * 推导式的性能优势 * 何时使用推导式,何时使用普通循环 列表推导式是Python的标志性特性,简洁而高效。但记住:可读性第一,不要为了使用推导式而牺牲代码清晰度。 下一章:[[python_course:chapter07|第七章:字符串深度解析]] 登录 Detach Close 该主题尚不存在 您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。 python/chapter06.txt 最后更改: 2026/04/09 14:25由 张叶安 登录