ZetCode

Python __iter__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨 Python 的 __iter__ 方法,该特殊方法使对象可迭代。我们将介绍迭代协议、自定义迭代器、生成器函数和实际示例。

基本定义

__iter__ 方法返回一个实现迭代协议的迭代器对象。当需要迭代对象时,例如在 for 循环中,会调用它。

主要特点:它必须返回一个迭代器对象(该对象实现 __next__),启用对容器对象的迭代,并与 Python 的内置 iter() 函数一起使用。

基本 __iter__ 实现

这是一个简单的实现,展示了 __iter__ 如何使类可迭代。该示例演示了迭代的最低要求。

basic_iter.py
class MyIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return iter(self.data)

items = MyIterable([1, 2, 3])
for item in items:
    print(item)

此示例将迭代委托给内置的列表迭代器。 __iter__ 方法返回内部数据列表的迭代器。

iter() 函数在底层调用 __iter__。这是使对象与 for 循环一起使用的标准方法。

自定义迭代器类

我们可以通过实现 __iter____next__ 方法来创建自定义迭代器。这可以完全控制迭代行为。

custom_iterator.py
class CountDown:
    def __init__(self, start):
        self.current = start
        self.start = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < 0:
            raise StopIteration
        else:
            result = self.current
            self.current -= 1
            return result

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

这个倒计时迭代器返回从 start 到 0 的数字。由于该类本身就是一个迭代器,因此 __iter__ 返回 self。

__next__ 方法控制迭代逻辑,并在完成时引发 StopIteration。这是迭代器协议的要求。

生成器函数作为 __iter__

我们可以使用 __iter__ 中的生成器函数,而不是单独的迭代器类。 这通常更简洁易读。

generator_iter.py
class Squares:
    def __init__(self, limit):
        self.limit = limit
    
    def __iter__(self):
        for i in range(1, self.limit + 1):
            yield i * i

for square in Squares(5):
    print(square)

此示例生成数字的平方,直到达到限制。 __iter__ 方法使用 yield 自动创建生成器迭代器。

生成器函数通过自动处理 __next__ 和状态管理来简化迭代器实现。它们也节省内存。

迭代自定义数据结构

__iter__ 对于自定义数据结构特别有用,您希望控制在迭代期间如何访问元素。

custom_structure.py
class TreeNode:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
    
    def __iter__(self):
        if self.left:
            yield from self.left
        yield self.value
        if self.right:
            yield from self.right

tree = TreeNode(4,
    TreeNode(2, TreeNode(1), TreeNode(3)),
    TreeNode(6, TreeNode(5), TreeNode(7))
)

for value in tree:
    print(value)  # Prints 1-7 in order

此二叉树通过 __iter__ 实现中序遍历。 yield from 以递归方式委托给子节点的迭代器。

这种模式适用于任何树状结构,您希望在简单的迭代界面后面隐藏遍历的复杂性。

使用 __iter__ 进行惰性求值

__iter__ 可以实现惰性求值,在这种求值中,值仅在迭代期间需要时才计算,从而节省内存和 CPU 周期。

lazy_eval.py
class Fibonacci:
    def __iter__(self):
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a + b

import itertools
for fib in itertools.islice(Fibonacci(), 10):
    print(fib)

这个斐波那契数列生成器按需计算数字。 为了演示,无限序列可以安全地与 itertools.islice 一起使用。

对于大型或无限序列,惰性求值非常强大,因为预先计算所有值是不切实际或不可能的。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程