ZetCode

Python __next__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __next__ 方法,这是 Python 中迭代的特殊方法。我们将介绍迭代协议、自定义迭代器、生成器和实际示例。

基本定义

__next__ 方法是 Python 迭代器协议的一部分。它从迭代器返回下一个项目。当没有更多项目可用时,它会引发 StopIteration 异常。

主要特征:它不接受参数(除了 self),返回序列中的下一个值,并在调用之间维护内部状态。它与 __iter__ 协同工作以实现完整的迭代协议。

基本迭代器实现

这是一个简单的迭代器类,实现了 __iter____next__ 方法。这演示了基本的迭代器模式。

basic_iterator.py
class CountUpTo:
    def __init__(self, max):
        self.max = max
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current >= self.max:
            raise StopIteration
        self.current += 1
        return self.current - 1

counter = CountUpTo(5)
for num in counter:
    print(num)  # Prints 0 1 2 3 4

此迭代器从 0 向上计数到(但不包括)指定的最大值。__next__ 方法递增计数器并返回值,直到达到限制。

__iter__ 方法返回 self,使该对象既是迭代器又是可迭代对象。这对于简单的迭代器来说很常见。

无限迭代器

迭代器不必是有限的。此示例显示了一个无限迭代器,它无限期地生成斐波那契数。

infinite_iterator.py
class Fibonacci:
    def __init__(self):
        self.a, self.b = 0, 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 = Fibonacci()
for i, num in enumerate(fib):
    print(num)
    if i >= 9:  # Print first 10 numbers
        break

这个斐波那契迭代器永远不会引发 StopIteration,使其成为无限迭代器。我们使用 break 条件在外部控制迭代。

状态(当前的斐波那契数)在 __next__ 调用之间的实例变量中维护。这演示了有状态的迭代。

文件行迭代器

这个实际的示例创建了一个迭代器,它懒惰地从文件中读取行,这对于大型文件来说是内存高效的。

file_iterator.py
class FileLineIterator:
    def __init__(self, filename):
        self.file = open(filename)
    
    def __iter__(self):
        return self
    
    def __next__(self):
        line = self.file.readline()
        if not line:
            self.file.close()
            raise StopIteration
        return line.strip()
    
    def __del__(self):
        if hasattr(self, 'file') and self.file:
            self.file.close()

lines = FileLineIterator('data.txt')
for line in lines:
    print(line)

此迭代器一次从文件中读取一行,仅将所需的加载到内存中。它在迭代完成时正确关闭文件。

如果迭代器在完成之前被垃圾回收,则 __del__ 方法确保文件被关闭。这对于资源清理非常重要。

链式迭代器

此示例演示如何使用 __next__ 将多个迭代器链接在一起,从而创建一个单一的连续序列。

chain_iterators.py
class ChainIterators:
    def __init__(self, *iterables):
        self.iterables = iter(iterables)
        self.current = iter(next(self.iterables))
    
    def __iter__(self):
        return self
    
    def __next__(self):
        try:
            return next(self.current)
        except StopIteration:
            self.current = iter(next(self.iterables))
            return next(self.current)

chained = ChainIterators([1, 2, 3], 'abc', (4.5, 6.7))
for item in chained:
    print(item)  # Prints 1, 2, 3, 'a', 'b', 'c', 4.5, 6.7

此迭代器将多个序列链接在一起,在每个序列耗尽时无缝地从一个序列过渡到下一个序列。它处理任何可迭代的输入。

该实现使用嵌套的迭代器,捕获当前迭代器的 StopIteration 以移动到序列中的下一个迭代器。

具有重置功能的有状态迭代器

这个高级示例展示了一个可以重置为其初始状态的迭代器,展示了更复杂的 __next__ 行为。

resettable_iterator.py
class ResettableRange:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop
        self.reset()
    
    def reset(self):
        self.current = self.start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current >= self.stop:
            raise StopIteration
        result = self.current
        self.current += 1
        return result

ranger = ResettableRange(2, 5)
print(list(ranger))  # [2, 3, 4]
ranger.reset()
print(list(ranger))  # [2, 3, 4] again

此迭代器模仿 range 行为,但添加了一个 reset 方法来从头开始重新启动迭代。状态被维护,但可以根据需要重置。

reset 方法演示了如何从外部管理迭代器状态,从而提供对迭代行为的更多控制。

最佳实践

资料来源

作者

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

列出所有 Python 教程