#!/usr/bin/env python # coding: utf-8 # ## 复现 bug # ### print_iterator # 定义 `print_iterator` # In[1]: def print_iterator(iterator): while True: try: element = next(iterator) except StopIteration: break else: print(element) # 测试 print_iterator # In[3]: print_iterator(iter([1, 2, 3])) # 工作完全正常 # ### counter_iterable # 定义 counter_iterable # In[7]: def counter_iterable(iterable): iterator = iter(iterable) iterator_length = sum(1 for _ in iterator) print(iterator_length) # 测试 counter_iterable # In[6]: counter_iterable([1, 2, 3]) # 工作完全正常 # ### 组合在一起 # 定义 counter_iterable_and_print # In[9]: def counter_iterable_and_print(iterable): iterator = iter(iterable) iterator_length = sum(1 for _ in iterator) print(iterator_length) print_iterator(iterator) # 测试 counter_iterable_and_print # In[10]: counter_iterable_and_print([1, 2, 3]) # 工作不正常! # ## 原因 # `iterator` 内有有状态信息,具有不可重入(non-reentrant)的特性,这个和 `list`, `tuple`, `dict` 等容器不一样,容器通过 `__getitem__` 来迭代。 # 示例代码: # In[12]: iterable = [1, 2, 3] iterator = iter(iterable) iterator_length = sum(1 for _ in iterator) iterator_length_2 = sum(1 for _ in iterator) # In[13]: print(iterator_length) print(iterator_length_2) # ## 解决方案 # 每次循环都重新生成一个 iterator 对象 # In[14]: iterable = [1, 2, 3] iterator = iter(iterable) iterator_length = sum(1 for _ in iterable) iterator = iter(iterable) iterator_length_2 = sum(1 for _ in iterable) # In[15]: print(iterator_length) print(iterator_length_2)