Python Generator与Iterator对比:yield工作原理及内存差异疑问
解答
首先,你的猜想不完全准确:生成器确实是迭代器的一种,但并非“继承基础迭代器重写next”这么简单——Python的生成器是由解释器自动创建的特殊迭代器对象,而非基于用户自定义类的继承实现。
一、yield的工作原理
当你定义一个包含yield的函数时,Python解释器会把它标记为生成器函数。调用这个函数时,不会立即执行函数体代码,而是返回一个生成器对象。
每次调用next()(或通过for循环隐式调用)时,函数体才会执行,直到遇到yield语句:
- 执行到
yield时,返回yield后的值,同时暂停函数的执行状态(包括局部变量、当前执行位置等); - 下一次调用
next()时,函数从暂停的位置继续执行,直到再次遇到yield或执行完函数体(此时抛出StopIteration)。
二、内存差异的核心原因
对象结构的本质区别
- 自定义迭代器是你手动创建的类实例,它需要携带类本身的元数据(比如方法定义、继承链、类属性等),
sys.getsizeof(CustomIterator)统计的就是类对象的内存,这部分本身就占用了大量空间;而生成器是Python内置的轻量级迭代器,没有自定义类的额外元数据开销。 - 你的自定义迭代器实例还保存了
__position和__collection两个实例属性,而生成器内部仅保存最必要的执行状态(比如当前迭代位置、函数上下文),且这些状态由解释器高效管理,内存占用远低于自定义类实例。
- 自定义迭代器是你手动创建的类实例,它需要携带类本身的元数据(比如方法定义、继承链、类属性等),
内存统计的不公平对比
你在自定义迭代器的统计中加入了类对象的内存(sys.getsizeof(CustomIterator)),但生成器的统计里并没有包含生成器函数本身的内存——这部分是额外的、不必要的对比项。即使去掉类对象的内存,自定义迭代器实例的内存仍会比生成器对象大,因为生成器是解释器优化后的内置结构。解释器层面的优化
Python的生成器是专门为迭代场景设计的内置对象,经过了大量底层优化,内存占用被压缩到最小;而自定义迭代器类需要遵循Python通用的类对象模型,包含实例字典、类型指针等通用开销,这些都是生成器不需要的。
三、关于生成器与迭代器的关系
生成器本质上是迭代器的一种实现,它自动实现了__iter__和__next__方法:生成器对象的__iter__返回自身,__next__则对应yield的执行逻辑——但这是解释器自动为生成器生成的,并非用户手动继承重写。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

