如何在python的while循环语句中使用迭代器

Lea*_*ple 11 python iterator generator while-loop python-3.x

是否可以在 Python 的 while 循环中使用生成器或迭代器?例如,类似于:

i = iter(range(10))
while next(i):
    # your code
Run Code Online (Sandbox Code Playgroud)

这样做的目的是将迭代构建到 while 循环语句中,使其类似于 for 循环,不同之处在于您现在可以在 while 语句中添加额外的逻辑:

i = iter(range(10))
while next(i) and {some other logic}:
    # your code
Run Code Online (Sandbox Code Playgroud)

然后它成为一个很好的 for 循环/while 循环混合。

有谁知道如何做到这一点?

sch*_*ggl 16

在 Python < 3.8 中,您可以使用itertools.takewhile

from itertools import takewhile

i = iter(range(10))
for x in takewhile({some logic}, i):
    # do stuff
Run Code Online (Sandbox Code Playgroud)

这里的“一些逻辑”将是一个 1-arg 可调用对象,可以接收任何next(i)产量:

for x in takewhile(lambda e: 5 > e, i):
    print(x)
0
1
2
3
4
Run Code Online (Sandbox Code Playgroud)

在 Python >= 3.8 中,您可以使用赋值表达式执行以下操作:

i = iter(range(10))
while (x := next(i, None)) is not None and x < 5:
    print(x)
Run Code Online (Sandbox Code Playgroud)


tob*_*s_k 9

有两个问题 while next(i):

  1. for循环不同的是,如果没有值,while循环将不会捕获StopIteration引发的异常nextnext(i, None)在这种情况下,您可以使用返回“falsey”值,但是while只要迭代器返回实际的 falsey 值,循环也会停止
  2. 返回的值next将被消耗并且在循环体中不再可用。(在 Python 3.8+ 中,这可以通过赋值表达式解决,请参阅其他答案。)

相反,您可以使用forwith 循环itertools.takewhile,从可迭代对象或任何其他条件测试当前元素。这将循环直到迭代耗尽,或者条件评估为假。

from itertools import takewhile
i = iter(range(10))
r = 0
for x in takewhile(lambda x: r < 10, i):
    print("using", x)
    r += x
print("result", r)
Run Code Online (Sandbox Code Playgroud)

输出:

using 0
...
using 4
result 10
Run Code Online (Sandbox Code Playgroud)


lar*_*sks 5

您只需要安排您的迭代器在到期时返回类似 false 的值。例如,如果我们反转,range使其倒数到 0:

>>> i = iter(range(5, -1, -1))
>>> while val := next(i):
...     print('doing something here with value', val)
...
Run Code Online (Sandbox Code Playgroud)

这将导致:

doing something here with value 5
doing something here with value 4
doing something here with value 3
doing something here with value 2
doing something here with value 1
Run Code Online (Sandbox Code Playgroud)

  • 但这会消耗“next(i)”,如果您在循环体中再次调用它,则会错过一个值。不过,也许可以使用 Python 3.8 赋值表达式。 (2认同)