Python中的for-in循环是通过迭代协议实现的,该协议基于两个特殊方法:__iter__()和__next__()。当循环开始时,Python调用iter(obj)(寻找__iter__方法)。如果返回一个实现了__next__()的迭代器对象,循环便开始调用该方法以获取每一个接下来的元素。
如果元素成功返回,迭代将继续。当抛出StopIteration异常时,循环将结束。
自定义迭代器示例:
class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 for num in Counter(1, 3): print(num) # 输出 1, 2, 3
细微差别: 许多标准的Python结构实现了迭代器协议;您可以轻松地让自己的对象也这样。
可以在任何Python对象上使用for-in循环吗?可迭代对象与迭代器有什么区别?
答案: 不,for-in循环要求对象是可迭代的,也就是说,实现了返回迭代器的__iter__()方法(带有__next__()方法的对象)。迭代器通过__iter__()返回自身,而可迭代对象则不返回。
示例:
lst = [1, 2, 3] iterator = iter(lst) print(hasattr(lst, '__iter__')) # True print(hasattr(iterator, '__next__')) # True(迭代器) print(hasattr(lst, '__next__')) # False(不是迭代器)
故事
项目: 大文件处理。
问题: 在项目中尝试重复遍历文件对象(逐行迭代文件)两次,而不显式打开新文件 — 在第二次迭代时没有获取到任何行(指针已经在文件末尾!)。
故事
项目: 将自定义集合类与框架集成。
问题: 类仅实现了
__getitem__,而未实现__iter__,不兼容生成器和标准循环(for)。因此,第三方库出现了问题,期待得到一个迭代器。
故事
项目: 在自定义集合上使用map/filter。
问题: 自定义列表类未实现
__iter__和__next__,与许多标准Python函数不兼容,这在集成测试后才显现出来,并且需要重大重构。