You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:30:54