使用break时在python生成器中的yield语句之后运行代码

Lea*_*Man 2 python generator break

我有一个简单的生成器:

def counter(n): 
   counter = 0
   while counter <= n:
      counter += 1
      yield counter
   print(f"Nice! You counted to {counter}")

def test_counter(): 
   for count in counter(6): 
      print(f"count={count}")
      if count > 3: 
         break
Run Code Online (Sandbox Code Playgroud)

在这个例子中,当计数达到 3 时有一个中断。但是代码的唯一问题是中断在 yield 语句终止了生成器的执行。它不会在 yield 语句之后运行 print 语句。有没有办法在发生中断时在 yield 语句之后的生成器中执行代码?

示例运行:

# What happens: 
>>> test_counter()
count=1
count=2
count=3
count=4

# What I'd like to see: 
>>> test_counter()
count=1
count=2
count=3
count=4
Nice! You counted to 4
Run Code Online (Sandbox Code Playgroud)

Dan*_*iel 10

你必须把它print放在一个finally-block 中:

def counter(n): 
    try:
        counter = 0
        while counter <= n:
            counter += 1
            yield counter
    finally:
        print(f"Nice! You counted to {counter}")

def test_counter(): 
    for count in counter(6): 
        print(f"count={count}")
        if count > 3: 
            break
Run Code Online (Sandbox Code Playgroud)

  • 这确实很酷,但是,有一点警告:“finally”代码仅在计数器对象被销毁时执行。我认为在“for”循环中,那就是循环结束的时候(尽管我不是 100% 确定),但是如果你执行了“c = counter(6)”,然后执行了“for count in c”,那么你就可以d 得到“很好!” 仅当 c 被重新分配给其他东西时才打印,或者如果你不幸运的话,甚至可能永远不会打印。 (2认同)

Enz*_*nzo 5

您可以使用send生成器的方法:

def counter(n): 
   counter = 0
   while counter <= n:
      counter += 1
      should_continue = yield counter
      if should_continue == False:
          break

   print(f"Nice! You counted to {counter}")

def test_counter(): 
    gen = counter(6)
    for count in gen: 
        print(f"count={count}")
        if count > 3: 
            try:
                gen.send(False)
            except StopIteration:
                break
Run Code Online (Sandbox Code Playgroud)

现在test_counter()按预期工作。