【问题标题】:Using a Generator with a While loop in Python在 Python 中使用带有 While 循环的生成器
【发布时间】:2021-04-25 01:30:46
【问题描述】:

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

while next(gen):
    print(value_from_gen)

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

然后我创建一个生成器来返回值
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 循环来做到这一点?

【问题讨论】:

  • while val = next(g): 必须是 while val == next(g):
  • 不清楚您要做什么。为什么for v in g: print(v) 不起作用?
  • @BuddyBobIII 不,OP 正在尝试将 next(g) 的输出分配给 val,而不是比较它们
  • 好的,这就是错误的来源。如果 OP 知道这是错误,为什么要发布它?

标签: python generator


【解决方案1】:

基于@Brad Martsberger's answer,你也可以将False传递给next函数的默认参数:

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

【讨论】:

    【解决方案2】:

    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 是生成器中的有效条目,这将中断。您必须使用不能出现在生成器序列中的默认值。

    【讨论】:

    • while element:= next(g, None): 在第二种情况下会起作用
    • 我想你想要while (element := next(g, None)) is not None:,以防你的生成器产生其他错误结果,如空字符串、空列表等。还需要python 3.8或更高版本才能使用:=
    【解决方案3】:
    1. 记住赋值表达式 (:=) 是在 Python 3.8 中引入的

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

    3. 用while循环来实现,我觉得应该用try/except StopIteration,不过没意义,用for循环就好了,

    【讨论】:

      【解决方案4】:
      x = [1, 2, 3, 4, 5]
      g = ({i: i*2} for i in x)
      

      当生成器中没有元素可迭代时引发 StopIteration 异常。 您可能打算使用海象分配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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-06
        • 2016-01-17
        • 2014-10-21
        • 1970-01-01
        • 2021-08-21
        • 2021-11-04
        相关资源
        最近更新 更多