Python 3中可迭代对象iterable何时可替换为迭代器iterator
Python3 可迭代对象与迭代器互换判断规则
核心判断逻辑
迭代器本身就是可迭代对象的一种(迭代器实现了可迭代对象要求的__iter__方法,返回自身),判断二者能不能互换只需要看场景需求:
- 只要场景是仅需要遍历获取输入对象的所有元素,迭代器完全可以替换普通可迭代对象。所有标准库中接收可迭代对象作为参数的API,比如
collections.deque()、list()、tuple()、set()、itertools.islice()、for循环、推导式等,都可以直接传迭代器使用。 - 如果场景需要用到普通可迭代对象自身的专属属性/能力,就不能用迭代器替换。
示例现象解释
你碰到的两个场景差异完全符合上面的判断逻辑:
deque()、islice()的内部逻辑就是遍历输入参数取所有元素,不需要用到输入对象的其他能力,所以传列表或者列表迭代器的效果完全一致。print()不会主动遍历可迭代对象输出元素,它只会调用对象的__str__/__repr__方法输出自身的字符串表示:列表的字符串实现会输出内部所有元素,而迭代器的字符串实现只会输出类型和内存地址,所以你看不到预期的元素内容,本质是这个场景根本不需要遍历输入,所以替换后不符合预期。
替换的额外注意事项
就算是满足遍历场景的要求,替换时也要注意迭代器的一次性消耗特性:
- 普通可迭代对象(比如列表、元组、字典)支持反复遍历,每次遍历都会从头开始取元素
- 迭代器只能被遍历一次,遍历完成后就会被耗尽,再次遍历不会返回任何元素
如果你的业务逻辑需要多次遍历同一个输入对象,就不能用迭代器替换普通可迭代对象,示例如下:
ml = [1, 2, 3] iter_ml = iter(ml) # 普通列表可以多次遍历 print([i for i in ml]) # 输出 [1,2,3] print([i for i in ml]) # 再次遍历仍输出 [1,2,3] # 迭代器只能遍历一次 print([i for i in iter_ml]) # 首次遍历输出 [1,2,3] print([i for i in iter_ml]) # 再次遍历输出空列表
内容的提问来源于stack exchange,提问作者viral_mutant
相关产品推荐
相关产品推荐

