问题的背景: 可迭代性的概念出现在 Python 中,目的是统一对集合的操作:列表、字典、集合等。任何可以通过 for 循环遍历的对象都被视为可迭代的。这是通过特定的魔术方法实现的。
问题: Python 要求特定的协议以便循环和与序列相关的函数能够正确工作。如果用户在其类中错误地实现了这些协议,标准机制(for、list()、sum() 等)将无法正常工作或表现出意外的行为。
解决方案:
可迭代对象是实现了 __iter__ 方法的任何对象。迭代器则是实现了 __next__ 和返回 self 的 __iter__ 的对象。通常, __iter__ 返回的对象是迭代器,但这并非必需。示例:
class MyRange: def __init__(self, start, end): self.start = start self.end = end def __iter__(self): self.current = self.start return self def __next__(self): if self.current < self.end: val = self.current self.current += 1 return val raise StopIteration for x in MyRange(1, 4): print(x) # 1, 2, 3
关键特点:
__iter__ 方法来定义。__next__ 和 __iter__(返回 self)。__iter__ 返回新的对象是有效的实现。对于任何可迭代对象,__next__ 方法是必需的吗?
不是。可迭代对象只需要 __iter__,返回迭代器。__next__ 仅由迭代器本身实现。例如,list 没有 __next__ 方法,但它是可迭代的:它的 __iter__ 返回一个迭代器的实例。
lst = [1, 2, 3] print(hasattr(lst, '__next__')) # False
一个对象可以单独成为迭代器吗?
可以,如果它实现了 __iter__ 和 __next__ 两个方法。
可以为同一个集合创建多个状态独立的迭代器吗?
可以,如果 __iter__ 每次返回一个新的迭代器对象。
class MyList: def __init__(self, data): self.data = data def __iter__(self): return iter(self.data)
__next__ 而不实现 __iter__(或反之)。负面案例: 迭代器类在类级别存储状态(例如当前索引),而不是在实例中,这会导致并行遍历相互干扰。 优点:
积极案例:
每个迭代器在 __iter__ 中创建的实例中存储其状态。
优点: