Python 定义一个迭代器类(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言:为什么需要迭代器?

在编程世界中,迭代器(Iterator)如同图书馆的借阅员,它负责按顺序管理数据的“借阅流程”。无论是遍历列表、字典还是自定义数据结构,迭代器都在背后默默工作。对于 Python 开发者而言,理解如何定义一个迭代器类,不仅能提升代码的可维护性,还能在处理大规模数据时实现资源的高效利用。

本文将从迭代器的基础概念出发,逐步讲解如何定义一个迭代器类,并通过实际案例和代码示例,帮助读者掌握这一核心技能。无论你是编程初学者还是中级开发者,都能通过本文建立清晰的迭代器思维模型。


什么是迭代器?

在 Python 中,迭代器是一个遵循特定规则的对象。它必须实现两个核心方法:

  • __iter__(): 返回迭代器对象自身。
  • __next__(): 返回序列中的下一个值,当没有更多元素时抛出 StopIteration 异常。

迭代器与可迭代对象的区别

想象一个图书馆的场景:

  • 可迭代对象(Iterable):就像图书馆的目录列表,它知道所有书籍的位置,但无法直接“借出”书籍。
  • 迭代器(Iterator):更像是借阅员,它根据目录一步步取出书籍,并管理借阅顺序。

在 Python 中,列表、元组等内置类型都是可迭代对象,但它们本身不是迭代器。例如:

books = ["Python入门", "算法导论", "设计模式"]
book_iterator = iter(books)
print(next(book_iterator))  # 输出:Python入门

定义迭代器类的步骤

要定义一个迭代器类,需遵循以下步骤:

1. 创建类并实现 __iter__() 方法

这个方法必须返回迭代器对象自身,通常直接返回 self

class MyIterator:
    def __iter__(self):
        return self

2. 实现 __next__() 方法

这个方法负责生成下一个值,并在序列结束时抛出 StopIteration 异常。例如,一个简单的数字迭代器:

class NumberIterator:
    def __init__(self, max_value):
        self.max_value = max_value
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.max_value:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration

3. 使用迭代器

通过 iter()next() 函数调用:

num_iter = NumberIterator(3)
for num in num_iter:
    print(num)  # 输出:0 1 2

实战案例:斐波那契数列迭代器

斐波那契数列是迭代器应用的经典场景。我们可以定义一个迭代器类,按需生成前 N 项斐波那契数:

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

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.count:
            value = self.a
            self.a, self.b = self.b, self.a + self.b
            self.current += 1
            return value
        else:
            raise StopIteration

使用方式:

fib_iter = FibonacciIterator(5)
for num in fib_iter:
    print(num)  # 输出:0 1 1 2 3

迭代器的高级技巧

1. 使用生成器简化代码

生成器(Generator)是定义迭代器的便捷方式。通过 yield 关键字,可以将函数转化为迭代器:

def fibonacci_generator(count):
    a, b = 0, 1
    current = 0
    while current < count:
        yield a
        a, b = b, a + b
        current += 1

使用生成器与迭代器效果相同:

for num in fibonacci_generator(5):
    print(num)

2. 异常处理与无限迭代器

某些场景下,迭代器可能需要无限生成数据。例如,一个无限的斐波那契迭代器:

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

    def __iter__(self):
        return self

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

但需注意,无限迭代器需通过手动退出循环避免死循环:

fib_inf = InfiniteFibonacci()
for num in fib_inf:
    if num > 100:
        break
    print(num)

常见问题解答

Q1:为什么不能直接使用列表替代迭代器?

列表会一次性存储所有数据,而迭代器按需生成数据。例如,处理百万级数据时,迭代器能显著减少内存占用。

Q2:迭代器和生成器有什么区别?

  • 迭代器:需要显式定义类,并实现 __iter____next__ 方法。
  • 生成器:通过 yield 关键字自动生成迭代器逻辑,代码更简洁。

Q3:如何避免 StopIteration 异常?

for 循环中,Python 会自动捕获 StopIteration,因此无需手动处理。但在手动调用 next() 时,需用 try-except 块:

my_iter = iter([1, 2, 3])
try:
    while True:
        print(next(my_iter))
except StopIteration:
    pass

总结:迭代器的核心价值

通过定义一个迭代器类,我们能:

  1. 解耦数据生成与遍历逻辑:将数据生成规则封装在类中,提升代码复用性。
  2. 实现高效内存管理:按需生成数据,适合处理大数据集或无限序列。
  3. 扩展 Python 的迭代协议:自定义迭代行为,满足特定业务需求。

建议读者通过以下步骤巩固知识:

  1. 重新实现斐波那契迭代器类;
  2. 尝试将现有代码中的列表替换为迭代器;
  3. 探索 itertools 模块中的高级迭代工具。

掌握迭代器的定义与使用,将帮助你在 Python 开发中更优雅地处理数据流,这也是构建高性能应用的重要基石。

最新发布