回答问题

考虑以下 Python 代码:

b = [1,2,3,4,5,6,7]
a = iter(b)
for x in a :
    if (x % 2) == 0 :
        print(next(a))

哪个将打印 3、5 和 7。是否在可靠构造上迭代的变量上使用next(您可以假设 StopIteration 异常不是问题或将被处理),或者迭代器的修改是looped over inside loop 是否违反了某些原则?

Answers

在协议方面或理论上没有任何_错误_会阻止您编写此类代码。用尽的迭代器it将在每次后续调用it.__next__时抛出StopIteration,因此从技术上讲,for循环不会介意在循环体中使用next/__next__调用来耗尽迭代器。

我建议不要编写这样的代码,因为该程序将很难推理。如果场景变得比你在这里展示的更复杂一点,至少我必须用笔和纸完成一些输入并弄清楚发生了什么。

实际上,假设您要打印前面有偶数的每个数字,您的代码片段甚至可能不像您认为的那样。

>>> b = [1, 2, 4, 7, 8]                                              
>>> a = iter(b)                                                      
>>> for x in a: 
...:    if x%2 == 0: 
...:        print(next(a, 'stop'))                                   
4
stop

为什么7前面是偶数4却被跳过了?

>>>> a = iter(b)                                                      
>>>> for x in a: 
...:     print('for loop assigned x={}'.format(x)) 
...:     if x%2 == 0: 
...:         nxt = next(a, 'stop') 
...:         print('if popped nxt={} from iterator'.format(nxt)) 
...:         print(nxt)
...:                                               
for loop assigned x=1
for loop assigned x=2
if popped nxt=4 from iterator
4
for loop assigned x=7
for loop assigned x=8
if popped nxt=stop from iterator
stop

原来x = 4从未被for循环分配,因为显式next调用在for循环有机会再次查看迭代器之前从迭代器中弹出了该元素。

那是我在阅读代码时讨厌弄清楚细节的事情。


如果要在“(element, next_element)”对中迭代可迭代(包括迭代器),请使用itertools文档中的pairwise配方。

from itertools import tee                                         

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return zip(a, b) 

演示:

>>> b = [1,2,3,4,5,6,7]                                               
>>> a = iter(b)                                                       
>>>                                                                   
>>> for x, nxt in pairwise(a): # pairwise(b) also works 
...:    print(x, nxt)                                                                      
1 2
2 3
3 4
4 5
5 6
6 7

一般来说,itertools及其配方提供了许多强大的抽象来编写可读的迭代相关代码。更有用的助手可以在more_itertools模块中找到,包括pairwise的实现。

Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐