如何像调用函数一样调用迭代器

时间:2018-11-07 15:43:11

标签: python

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

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魔术可以使这段代码优雅?

3 个答案:

答案 0 :(得分:3)

将生成器实例化为对象,然后调用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循环内。

答案 1 :(得分:1)

您可以从islice导入itertools并这样写:

for _ in islice(iter(foo, False), n):
    # do stuff

只要不产生foo,但最多产生False次,它将调用n

但是,我个人喜欢

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

更好。它长了两行,但可读性更高。

答案 2 :(得分:-1)

只需使用一个计数器即可。

count = 0
while not foo():
    count += 1
    if count > 1000:
        break

    # Do things and stuff here