编程Python 开发人员

解释一下 Python 中的生成器是什么。它们是如何工作的,有什么用途,以及与列表表达式的区别是什么?

用 Hintsage AI 助手通过面试

答案。

生成器是 Python 中的特殊可迭代对象,它们允许按需创建序列,而无需同时占用整个集合的内存。它们通过带有关键字 yield 的函数或生成器表达式 ((expr for ... in ...)) 实现。在处理大量数据或潜在的无限流时,这种方法非常方便。

与列表表达式的关键区别:

  • 列表表达式 ([x for x in range(10)]) 会立即在内存中创建整个列表。
  • 生成器 ((x for x in range(10))) 会逐个创建元素,消耗的内存要少得多。

何时使用生成器:

  • 如果不需要通过索引访问元素。
  • 如果数据太大,无法存储在内存中。
  • 在组织数据流处理时(例如,读取文件行)。
# 生成器函数 def counter(n): for i in range(n): yield i for number in counter(5): print(number)

具有迷惑性的问题。

"使用带有 yield 的函数和普通返回列表的函数有什么区别?请举例说明。"

答案: 普通函数立即计算并返回列表,占用所有元素的内存。带有 yield 的函数返回生成器,逐个返回元素,并且不会立即加载整个序列到内存中。

def make_list(n): return [i for i in range(n)] # 立即返回列表,占用大量内存 def make_generator(n): for i in range(n): yield i # 将逐个返回元素

由于对主题细节的不熟悉而导致的实际错误示例。


故事

在一个分析大型日志的项目中,使用列表表达式提取包含错误的行:

error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]

文件超过 2 GB,应用程序由于 OOM(内存溢出)崩溃。应该使用生成器:

error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)

故事

一名员工想分析一个短列表,编写了一个带有 yield 的函数,但忘记了返回的是生成器,而不是列表:

result = my_generator_function() # result 是生成器,而不是列表 if len(result) > 5: # TypeError: object of type 'generator' has no len()

修正方法:将结果包裹在 list() 中。


故事

尝试多次迭代生成器:

numbers = (i for i in range(5)) for n in numbers: pass # 耗尽了生成器 for n in numbers: print(n) # 不输出任何内容

生成器是一次性的。要重复使用,需要创建一个新的生成器。