Python中iter()函数原理及自定义迭代器地址异常问题咨询
自定义可迭代类iter()行为问题解答
问题核心
创建自定义可迭代类LettersIter后,对其实例调用iter()函数时出现两个矛盾现象:两次调用返回相同内存地址,但两个对象却不相等。核心疑问:
- 为何内存地址相同却不是同一对象?
iter()函数的底层工作机制是怎样的?- 它是否包装生成器函数并返回生成器对象?
- 为何两次调用会返回相同地址?
代码示例
class LettersIter: def __init__(self, start='a', end='e'): self.next_letter = start self.end = end def __next__(self): if self.next_letter == self.end: raise StopIteration letter = self.next_letter self.next_letter = chr(ord(letter)+1) return letter def __iter__(self): start = self.next_letter while start < self.end: yield start start = chr(ord(start)+1) class Letters: def __init__(self, start='a', end='b'): self.start = start self.end = end def __iter__(self): return LettersIter(self.start, self.end) letter_iter = Letters('d', 'r') first_iterator = iter(letter_iter) print(iter(first_iterator) == iter(first_iterator)) # False print(iter(first_iterator)) # <generator object LettersIter.__iter__ at 0x00000238211D9938> print(iter(first_iterator)) # <generator object LettersIter.__iter__ at 0x00000238211D9938> print(next(first_iterator)) # d print(next(iter(first_iterator))) # e
问题解答
1. 内存地址相同但对象不等的原因
这是内存地址复用导致的:每次调用iter(first_iterator)都会执行LettersIter.__iter__生成一个全新的生成器对象。第一个生成器打印后没有被任何变量引用,Python垃圾回收器会立即销毁它并释放对应内存地址;第二个生成器创建时,刚好复用了这个被释放的地址。但这两个是完全独立的对象,所以==比较返回False。
2. iter()函数的底层工作机制
iter(obj)的执行逻辑分三步:
- 优先调用对象的
__iter__方法,直接返回该方法的执行结果; - 如果对象没有
__iter__但实现了__getitem__,Python会自动创建一个默认迭代器,按索引从0开始逐个获取元素; - 若两者都未实现,直接抛出
TypeError。
注意:标准迭代器(实现__next__的对象)默认的__iter__是返回自身,但你给LettersIter手动实现了生成器版的__iter__,所以每次调用iter(first_iterator)都会生成新的生成器,而非返回first_iterator本身。
3. iter()是否包装生成器函数?
不是。生成器对象是由包含yield的生成器函数直接返回的——调用生成器函数时,不会执行函数体,而是立刻返回一个生成器对象。这里iter()只是调用了LettersIter.__iter__这个生成器函数,拿到它返回的生成器而已,没有额外包装逻辑。
4. 两次调用返回相同地址的原因
本质是Python内存管理器的优化行为:短时间内创建的临时对象被销毁后,其内存地址很容易被后续创建的同类型对象复用,以此减少内存碎片、提升分配效率。
内容的提问来源于stack exchange,提问作者yujian xue
相关产品推荐
相关产品推荐

