Python自定义迭代器的实现方法

 更新时间:2026年05月29日 09:38:36   作者:一天 24h  
自定义迭代器的核心是严格遵守 Python 迭代器协议,只要一个类实现了__iter__()和__next__()这两个特殊方法,它的实例就是一个合法的迭代器,本文给大家介绍了Python自定义迭代器的实现方法,需要的朋友可以参考下

引言

自定义迭代器的核心是严格遵守 Python 迭代器协议。只要一个类实现了__iter__()__next__()这两个特殊方法,它的实例就是一个合法的迭代器。

一、迭代器协议的核心要求

任何自定义迭代器都必须满足以下两个条件:

  1. __iter__(self):必须返回迭代器对象本身(return self)。这是为了让迭代器可以直接用在for循环等接受可迭代对象的地方。
  2. __next__(self)
    • 返回序列中的下一个元素
    • 更新内部状态,指向下一个元素
    • 当没有更多元素时,必须抛出StopIteration异常

二、第一个自定义迭代器:生成指定范围的偶数

我们从最简单的例子开始,实现一个能生成从startend之间所有偶数的迭代器:

class EvenIterator:
    def __init__(self, start, end):
        # 初始化迭代器的状态
        self.current = start if start % 2 == 0 else start + 1  # 确保从偶数开始
        self.end = end

    def __iter__(self):
        # 迭代器必须返回自己
        return self

    def __next__(self):
        if self.current > self.end:
            # 没有更多元素,抛出异常终止迭代
            raise StopIteration
        # 保存当前值
        result = self.current
        # 更新状态,指向下一个偶数
        self.current += 2
        # 返回当前值
        return result

使用这个迭代器

# 创建迭代器实例
even_iter = EvenIterator(1, 10)

# 1. 使用next()手动遍历
print(next(even_iter))  # 输出:2
print(next(even_iter))  # 输出:4
print(next(even_iter))  # 输出:6

# 2. 直接用for循环遍历(自动处理next()和StopIteration)
for num in EvenIterator(1, 10):
    # end控制每个输出的数用空格隔开,默认是换行‘\n'
    print(num, end=' ')  # 输出:2 4 6 8 10

三、深入理解:迭代器的工作原理

1. 为什么__iter__()必须返回 self?

因为 Python 中所有接受 "可迭代对象" 的地方(for循环、list()sum()等),都会先调用iter(对象)获取迭代器。

如果__iter__()返回的不是 self,那么for循环拿到的就是另一个对象,而不是我们的迭代器本身,迭代逻辑就会失效。

2. 迭代器的 "一次性" 特性

迭代器的状态是不可逆的,一旦遍历到末尾,就无法再从头开始:

even_iter = EvenIterator(1, 10)

# 第一次遍历:正常输出
print(list(even_iter))  # 输出:[2, 4, 6, 8, 10]

# 第二次遍历:空列表!
print(list(even_iter))  # 输出:[]

这是因为第一次遍历后,self.current已经变成了 12,再调用next()会直接抛出StopIteration

3. 如何实现可多次遍历的 "可迭代对象"?

如果需要多次遍历,应该将可迭代对象迭代器分开实现:

  • 可迭代对象:实现__iter__(),每次返回一个新的迭代器实例
  • 迭代器:实现__iter__()__next__()
# 可迭代对象(可以多次遍历)
class EvenNumbers:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        # 每次调用iter()都返回一个新的迭代器
        return EvenIterator(self.start, self.end)

# 现在可以多次遍历了
evens = EvenNumbers(1, 10)
print(list(evens))  # 输出:[2, 4, 6, 8, 10]
print(list(evens))  # 输出:[2, 4, 6, 8, 10]

四、实用自定义迭代器示例

示例 1:逆序遍历列表的迭代器

class ReverseIterator:
    def __init__(self, data):
        self.data = data
        self.index = len(data)  # 从最后一个元素的下一个位置开始

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index -= 1
        return self.data[self.index]

# 使用
for char in ReverseIterator('hello'):
    print(char, end=' ')  # 输出:o l l e h

示例 2:无限斐波那契数列迭代器

这是迭代器最强大的应用之一 —— 生成无限序列

class FibonacciIterator:
    def __init__(self):
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        result = self.a
        self.a, self.b = self.b, self.a + self.b
        return result

# 使用:按需生成,永远不会结束
fib = FibonacciIterator()
for _ in range(15):
    print(next(fib), end=' ')  # 输出:0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

示例 3:分批处理数据的迭代器

class BatchIterator:
    def __init__(self, data, batch_size):
        self.data = data
        self.batch_size = batch_size
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        # 计算当前批次的结束位置
        end = self.index + self.batch_size
        # 切片获取当前批次
        batch = self.data[self.index:end]
        # 更新索引
        self.index = end
        return batch

# 使用
data = list(range(100))
for batch in BatchIterator(data, 10):
    print(f"处理批次:{batch}")
    # 在这里处理每一批数据

五、更简单的方式:生成器(Generator)

手动实现__iter__()__next__()虽然清晰,但比较繁琐。Python 提供了生成器,可以用更简洁的语法创建迭代器。

生成器使用yield关键字,自动实现了迭代器协议:

# 生成器函数:等价于上面的EvenIterator
def even_generator(start, end):
    current = start if start % 2 == 0 else start + 1
    while current <= end:
        yield current  # 暂停执行,返回当前值
        current += 2

# 使用方式和迭代器完全一样
for num in even_generator(1, 10):
    print(num, end=' ')  # 输出:2 4 6 8 10

生成器的优势

  1. 代码更简洁:不需要定义类和两个特殊方法
  2. 自动管理状态:Python 会自动保存函数的执行状态
  3. 可读性更高:逻辑更直观,更容易理解

生成器表达式

对于简单的迭代逻辑,还可以使用生成器表达式,这是创建迭代器的最简洁方式:

# 生成器表达式:等价于even_generator(1, 10)
even_gen = (x for x in range(1, 11) if x % 2 == 0)

print(list(even_gen))  # 输出:[2, 4, 6, 8, 10]

六、手动实现 vs 生成器:如何选择?

实现方式优点缺点适用场景
手动实现迭代器完全控制迭代逻辑,灵活性最高代码繁琐,容易出错复杂的迭代逻辑、需要维护复杂状态
生成器函数代码简洁,可读性高,自动管理状态灵活性稍低大多数场景,尤其是中等复杂度的迭代逻辑
生成器表达式最简洁,一行代码搞定只能实现简单逻辑简单的转换、过滤操作

七、自定义迭代器的常见坑

  1. 忘记在__next__()中抛出StopIteration:会导致无限循环
  2. __iter__()没有返回 self:迭代器无法用在 for 循环中
  3. 迭代器状态没有正确更新:会导致重复返回同一个元素或跳过元素
  4. 试图多次遍历同一个迭代器:第二次遍历会得到空结果

八、总结:自定义迭代器的步骤

  1. 定义一个类
  2. __init__()方法中初始化迭代器的状态
  3. 实现__iter__()方法,返回 self
  4. 实现__next__()方法:
    • 检查是否还有更多元素
    • 如果没有,抛出StopIteration
    • 如果有,计算并返回当前元素
    • 更新内部状态,指向下一个元素

总而言之:自定义迭代器是 Python 迭代机制的底层核心,通过遵守迭代器协议,我们可以实现高效、灵活的数据遍历。生成器是简化版的自定义迭代器,适用于大多数场景;而手动实现类则提供了最高的灵活性,满足复杂的迭代需求。

以上就是Python自定义迭代器的实现方法的详细内容,更多关于Python自定义迭代器实现的资料请关注脚本之家其它相关文章!

相关文章

  • MxNet预训练模型到Pytorch模型的转换方式

    MxNet预训练模型到Pytorch模型的转换方式

    这篇文章主要介绍了MxNet预训练模型到Pytorch模型的转换方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • 一文详解5个你可能不知道但非常有用的Python库

    一文详解5个你可能不知道但非常有用的Python库

    Python作为当今最流行的编程语言之一,其强大的生态系统是其成功的关键因素,在这个庞大的生态系统中,除了众所周知的NumPy、Pandas、Requests等明星库外,还隐藏着许多功能强大但鲜为人知的瑰宝,本文呢就为大家盘点了一些你可能不知道但非常有用的Python库
    2025-11-11
  • Python 第一步 hello world

    Python 第一步 hello world

    Python 第一步 hello world 入门学习。
    2009-09-09
  • 一起来学习Python的元组和列表

    一起来学习Python的元组和列表

    这篇文章主要为大家详细介绍了Python元组和列表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 通过python-turtle库实现绘制图画

    通过python-turtle库实现绘制图画

    turtle库是python的基础绘图库,经常被用来给孩子们介绍编程知识的方法库,是标准库之一,利用turtle可以制作很多复杂的绘图。本文将为大家介绍通过turtle库绘制的一些有趣的图画,感兴趣的小伙伴可以学习一下
    2021-12-12
  • Python&Matlab实现炫酷的3D旋转图

    Python&Matlab实现炫酷的3D旋转图

    这篇文章主要为大家介绍了如何利用Python和Matlab分别实现酷炫的3D旋转图,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-04-04
  • 详解Python中type与object的恩怨纠葛

    详解Python中type与object的恩怨纠葛

    估计很多人都会有这样一个困惑,object 的类型是 type,但它同时又是 type 的基类,这是怎么做到的?带着这个疑问,我们开始本文的内容
    2023-04-04
  • Python使用正则表达式获取网页中所需要的信息

    Python使用正则表达式获取网页中所需要的信息

    这篇文章主要介绍了Python使用正则获取网页中所需要的信息的相关资料,需要的朋友可以参考下
    2018-01-01
  • bat和python批量重命名文件的实现代码

    bat和python批量重命名文件的实现代码

    这篇文章主要介绍了bat和python批量重命名文件的实现代码,需要的朋友可以参考下
    2016-05-05
  • 使用Python开发Telegram Bot的流程步骤

    使用Python开发Telegram Bot的流程步骤

    Telegram Bot 是一种可以与用户交互的机器人应用程序,通过 Telegram 的 Bot API 与服务器通信,它可以用来处理消息、执行命令、提供服务,如通知提醒、数据查询和自动化任务等,本文给大家介绍了如何用 Python 开发一个 Telegram Bot,需要的朋友可以参考下
    2025-01-01

最新评论