使用列表推导式 列表推导式创建列表
论文探讨了Python中如何将中断的循环和条件语句“格式化”为更简洁、的代码结构。重点讲解了列表推导式和生成器表述的正确语法、它们在内存使用和执行方式上的关键区别。通过具体的代码示例,揭示了常见的语法错误如何导致意外的生成器对象,并提供了处理文件时提高效率的最佳实践,帮助开发者编写更专业、更强的Python代码。1. 传统牛仔结构与代码修补需求
在python编程中,我们经常会遇到需要遍历数据并根据条件进行筛选和处理的场景。一种常见的实现方式是使用嵌套的for循环和if条件语句,例如从文件中读取行筛选出不包含特定单词的行:import re# 相当于file.txt 包含多行文本# 为演示目的,我们先创建一个虚拟文件 with open('file.txt', 'w') as f: f.writelines([ quot;这是没有单词的一行。\nquot;, quot;这是另一行。\nquot;, quot;单词开始这一行。\nquot;, quot;这一行在某处包含单词。\nquot;, quot;最后一行。\nquot; ])print(quot;--- 原始分辨率代码输出 ---quot;)with open('file.txt', 'r') as file: content = file.readlines() # 读取内容中的行的所有行到列表: # re.match(r'(?!word)', line) 检查行是否不为 quot;wordquot; 起始 if re.match(r'(?!word)', line): print(line.strip()) # .strip()删除行末的换符登录后复制
上述代码功能完善,但在某些情况下,特别是当逻辑网格更复杂时,锻造结构可能会降低代码的可执行性和简洁性。Python提供了“围巾化”等结构的强大工具:列表推导式(List Compressives)和生成器表达式(Generator Expressions)。2. 它的列表推导方式:简洁高效的数据构建
列表推导方式是一种从现有的可迭代对象创建新列表的简洁方式。它的语法结构通常是 [expression for item in iterable if condition]。能够将循环和条件判断合并到一行,从而使代码更加简洁和易读。
将上述文件处理的例子用列表推导进行“梳理化”:import reprint(quot;\n--- 列表推导式梳理化代码输出 ---quot;)with open('file.txt', 'r') as file: # 方式再一:先读取所有行到列表,用列表推导处理 content = file.readlines() Filtered_lines_list = [line.strip() for line in content if re.match(r'(?!word)', line)] for line infiltered_lines_list: print(line)# 注意:如果文件对象已被 readlines() 费,需要重新打开或使用eek(0)# 方式二:直接在文件对象上使用列表推导式(更推荐,用readlines())# with open('file.txt', 'r') as file: # 假设这里是重新打开的文件对象#filtered_lines_list_direct = [line.strip() 用于文件中的行 if re.match(r'(?!word)', line)]# for line infiltered_lines_list_direct:# print(line)登录后复制
列表推导式会一次性构建并返回一个完整的列表。这意味着如果处理的数据量很大,它可能会占用焦点的内存。
立即学习“Python免费学习笔记(深入)”;3. 它生成器表达式:用于求值与内存优化
与列表推导类似,生成器表达式也提供了一种简洁的语法来创建可迭代对象。但关键区别在于,生成器表达式使用圆括号 () 而不是方括号 [],并且立即不会构建整个列表,而是返回一个生成器对象(Generator)这个生成器对象在被迭代时生成值,实现了“调用求值”。
对于处理大型文件或无限序列等场景,生成器表达式是更优的选择,因为它能显着节省内存。
import reprint(quot;\n--- 生成器表达式代码输出(取求值) ---quot;)with open('file.txt', 'r') as file: # 使用生成器表达式filtered_lines_gen = (line.strip() for line in file if re.match(r'(?!word)', line)) # 此时filtered_lines_gen是一个生成器对象,尚未生成任何行 print(fquot;类型: {type(filtered_lines_gen)}quot;) # 输出: lt;class 'generator'gt; for line infiltered_lines_gen: # 迭代时,生成器将会计算并返回下一行 print(line) 登录后复制4. 常见陷阱:意外的生成器对象
在尝试“漂白”代码时,一个常见的错误是干扰列表推导式和生成器表达式的语法,或者不是本地生成器对象,从而导致意外的输出,例如[at 0x...gt;]。
用户在原始问题中遇到的错误[at 0x...gt;]通常发生在以下情况:语法混乱:想要列表推导式,但错误地使用了生成器表达式的圆表达式,然后又将该生成器表达式不本地放置了另一个列表或元组中。例如,如果写成 [ (line for line in content if condition) ],将创建一个包含一个生成器表达式的圆的列表。未迭代生成器:创建了一个生成器对象,但没有创建通过 for 循环或 next()函数本身进行迭代以获取其元素,而是直接打印了包含该生成器对象的列表或元组。
让我们通过一个提示来删除并解释这种“意外的生成器对象”:import reprint(quot;\n--- 常见陷阱:将生成器对象调用列表 ---quot;)with open('file.txt', 'r') as file: content = file.readlines() # 错误示例:明白是生成列表,但错误地使用了生成器表达式的逗号, # 然后又用方括号将其包起来。 # 这会创建一个只包含一个生成器对象的列表。
Problems_list_of_gen = [(line for line in content if re.match(r'(?!word)', line))] print(fquot;problematic_list_of_gen 的类型: {type(problematic_list_of_gen)}quot;) print(fquot;problematic_list_of_gen 的内容: {problematic_list_of_gen}quot;) # 输出相似:problematic_list_of_gen 的内容: [lt;generator object lt;genexprgt; at 0x...gt;] print(quot;\n迭代 Problems_list_of_gen:quot;) for item in Problems_list_of_gen: # 这里的 item 注明就是那个生成器对象本身,而不是文件中的一行 print(fquot;迭代中的元素: {item}quot;) # 打印是生成器对象 # 如果想获取生成器中的行,再次需要迭代 item # print(quot;从生成器中获取的实际行:quot;) # for effective_line in item: # print(actual_line.strip())登录后复制
这个示例声音地显示了,当一个生成器表达式被创建后,如果它被包裹在一个列表中(例如[(...)]),那么这个列表的元素将是生成器对象本身,而不是生成器所产生的具体数据。在循环中直接打印这个列表的元素,就会看到生成器对象
以上就是Python中列表推式导与生成器表达式的正确使用与常见陷阱的详细内容,更多请关注乐哥常识网相关文章!