Skip to main content

Python 迭代器

Python 自定义迭代器

(关于什么是类、对象,后续教程会详细说明) 在 Python 中,自定义迭代器可以通过创建一个类来实现,该类需要实现两个特殊方法:__iter__ 和 __next__。这允许你定义一个可以被 for 循环遍历的对象,或者通过 next() 函数逐个获取元素。

1. 核心概念

要创建一个自定义迭代器,你的类需要实现以下两个方法:

  • __iter__(self):返回迭代器对象本身(通常是 self)。
  • __next__(self):返回迭代序列中的下一个元素。如果没有更多元素,则抛出 StopIteration 异常。

这些方法使得你的对象可以被 Python 的迭代协议识别,允许它像内置的可迭代对象(如列表或字符串)一样被遍历。

2. 自定义迭代器

让我们创建一个简单的自定义迭代器,用于遍历一个数字列表。

class MyIterator:
    def __init__(self, data):
        self.data = data  # 存储要迭代的数据
        self.index = 0    # 跟踪当前索引

    def __iter__(self):
        return self       # 返回迭代器对象本身

    def __next__(self):
        if self.index < len(self.data):
            result = self.data[self.index]  # 获取当前元素
            self.index += 1                 # 移动到下一个索引
            return result
        else:
            raise StopIteration             # 迭代结束,抛出异常

# 使用自定义迭代器
my_iter = MyIterator([1, 2, 3, 4])
for item in my_iter:
    print(item)

输出:

1
2
3
4

说明:

  • __init__ 初始化迭代器,接受一个数据列表并设置初始索引为 0。
  • __iter__ 返回迭代器对象(self)。
  • __next__ 返回当前元素并递增索引,如果索引超出数据长度,则抛出 StopIteration
  • for 循环在内部调用 iter(my_iter) 获取迭代器,然后反复调用 next() 直到遇到 StopIteration

3. 自定义无限迭代器

迭代器不仅限于有限序列,也可以生成无限序列。以下是一个生成斐波那契数列的无限迭代器示例(限制输出前几个数)。

class FibonacciIterator:
    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_iter = FibonacciIterator()
for _ in range(6):
    print(next(fib_iter))

输出:

0
1
1
2
3
5

说明:

  • 这个迭代器生成无限的斐波那契数列。
  • __next__ 每次返回当前值并更新 ab 以生成下一个值。
  • 使用 next() 手动控制迭代次数,避免无限循环。

4. 注意事项和最佳实践

  1. 与生成器的区别:生成器(使用 yield)是更简单的创建迭代器的方式,但自定义迭代器类提供了更强的控制能力,适合复杂逻辑。
  2. 内存效率:迭代器按需生成值,适合处理大数据或动态序列。
  3. 调试技巧:可以用 next() 手动测试迭代器,确保 __next__ 的逻辑正确。

单次迭代:默认情况下,迭代器只能遍历一次。遍历完成后,索引或状态不会重置。如果需要再次迭代,必须创建新的迭代器对象。

even_iter = EvenNumbers(2, 6)
print(list(even_iter))  # 输出: [2, 4, 6]
print(list(even_iter))  # 输出: [] (已耗尽)

要再次迭代,需重新实例化:

even_iter = EvenNumbers(2, 6)
print(list(even_iter))  # 输出: [2, 4, 6]