首页 > 解决方案 > 如何像调用函数一样调用迭代器

问题描述

我需要一个看门狗机制来防止无限循环。这看起来像这样:

def stop(n):
    """ Returns False after n calls """ 
    for _ in range(n):
        yield True
    yield False

我会这样使用它:

def foo():
    # this is the function I have to watch
    return True # not good!

while foo() and stop(1000):
    # do some stuff

当然上面的代码不起作用,因为 stop(1000) 是一个迭代器。我可以通过使用全局变量来编写一个模仿 stop() 的函数,但它不会很 Pythonic。我也可以这样写:

for _ in range(n): 
    if not foo(): 
        break
    # do_some_stuff()

它有效,但不是很优雅,因为 range(n) 是次要的。是否有任何 Python 魔法可以让这段代码变得优雅?

标签: python

解决方案


将生成器实例化为对象并调用next()

def stop(n):
    """ Returns False after n calls """ 
    for _ in range(n):
        yield True
    yield False

my_stop = stop(1000)

while not foo() and next(my_stop):
    # do your things

这将确保它继续返回到生成器的同一实例并在 1000 次尝试后停止。另外据我推测,您似乎打算在foo()返回时打破True?如果是这样,则应not foo()改为捕获。

虽然完全是 Pythonic,但我认为只使用 for 循环:

# Just realized @timgeb answered the same alternative...
for _ in range(1000):
    if foo():
        break

您的stop()生成器实际上与 for 循环做同样的事情,只是返回它是否仍在 for 循环内。


推荐阅读