编程后端开发人员

在 Python 中,什么是可迭代对象,如何正确实现用户定义的可迭代对象?

用 Hintsage AI 助手通过面试

答案

问题的背景: 可迭代性的概念出现在 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__(或反之)。
  • 将状态记忆在类级别,而不是实例级别,从而导致在多次遍历时的 bug。

实际示例

负面案例: 迭代器类在类级别存储状态(例如当前索引),而不是在实例中,这会导致并行遍历相互干扰。 优点:

  • 更少的内存(只有一个索引)。 缺点:
  • 同时执行的两个循环时出现错误。

积极案例: 每个迭代器在 __iter__ 中创建的实例中存储其状态。 优点:

  • 多个迭代器的正确工作。 缺点:
  • 稍微多一点内存消耗。