在 Python 中使用带有 While 循环的生成器

Using a Generator with a While loop in Python

我希望能够做这样的事情:

while next(gen):
    print(value_from_gen)

我从这个列表开始 x=[1,2,3,4,5]

然后我为 return 值
创建一个生成器 g = ({i:i*2} for i in x)

当我尝试时:

while val = next(g):
    print(val)

我得到:

File "main.py", line 6
    while val = next(g):
              ^
SyntaxError: invalid syntax

当我尝试时:

while next(g):
    print(next())   

它跳过了一些值,我得到了错误:

{2: 4}
{4: 8}
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    print(next(g))
StopIteration

当我尝试时:

v= -1
while v is not None:
    v=next(g)
    print(v)

我得到了所有的值,但仍然得到错误:

{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10}
Traceback (most recent call last):
  File "main.py", line 8, in <module>
     v=next(g)
StopIteration

当我尝试时:

for v in g:
    print(v)

我得到正确的结果:

{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10} 

但是,我想知道这是否等同于调用 next(g) 并且它是否保留了生成器的惰性优势?

另外我想知道是否不可能用实际的 while 循环 来做到这一点?

  1. 记得赋值表达式(:=)是在Python3.8

    中引入的
  2. 你不用显式调用next(),for循环就是你想要的,它确实保持了生成器的惰性。

  3. 用while循环实现,我觉得应该用try/except StopIteration,但是没有意义,就用for循环,

forloop 版本保留了生成器的惰性,这将是实现您在这个问题中提出的问题的 pythonic 版本。

如果您想尝试将其强制进入 while 循环,您可以这样做

try:
    element = next(g)
    while True:
        print(element)
except StopIteration:
    pass

如果您不喜欢 try/except 您可以在下次调用时使用默认值

element = next(g, None)
while element is not None:
    print(element)

但是,如果 None 是您的生成器中的有效条目,这将中断。您必须使用一些不能出现在您的生成器序列中的默认值。

x = [1, 2, 3, 4, 5]
g = ({i: i*2} for i in x)

当生成器中没有要迭代的元素时引发 StopIteration 异常。 您可能打算使用 Walrus Assignment check here

try:
    while val := next(g): # walurs assignment added in Python3.8
        print(val)
except StopIteration:
    # StopIteration exception raised when no element left in generator to iterate over
    pass

next() 被调用两次

try:
    # This is totaly invalid syntax, because `next()` being call twise so you will have alternate number printed in console
    while next(g):
        #print(next()) # incorrect syntax
        print(next(g)) # correct syntax but `next()`calling twice
except StopIteration:
    pass

这是正确的,但您只需要应用异常处理。另外,最好使用 @Bard 提到的 pythonic 方式

try:
    v = -1
    while v is not None:
        v = next(g)
        print(v)
except StopIteration:
    pass

也基于, you may pass False to default parameter of next函数:

while element:= next(g, False):
    print(element)