2011-12-20 65 views
3

假设我有哪些咨询一些外部状态服务并返回一个值,为简单的功能,让我们假设值是一个整数:“迭代”函数的返回值

i = 10 
def foo(): 
    global i 
    i -= 1 
    return i 

很明显,我可以在它返回一个虚假值之前调用这个函数9次(第10次调用将返回0,这将在布尔上下文中计算为false)。

def take_while_truthy(func): 
    while True: 
     nextval = func() 
     if not nextval: 
      break 
     yield nextval 

然后:一些功能以这种方式工作,我现在可以用在发电机包装它 “迭代” 它

for x in take_while_truthy(foo): 
    print x 

给我:

9 
8 
[...] 
2 
1 

我问题是:标准库中的某个地方是否有更高级的函数,它可以执行此操作或类似的操作?我浏览了itertoolsfunctools,但没有发现任何与我想要做的事情非常相似的东西。我错过了什么吗?

+0

'itertools.takewhile'最接近,但对于这一点,你必须改变你的功能发电机或包裹在一个发电机。 – 2011-12-20 20:55:32

+1

http://docs.python.org/library/itertools.html#itertools.takewhile有什么问题?你在寻找'bool'作为谓词吗? – 2011-12-20 20:56:14

+0

'takewhile'需要一个迭代器 - 在我的情况下,该函数返回一个标量值,而不是一个生成器。 – dcrosta 2011-12-20 20:59:50

回答

8

这实际上可以使用内置的iter()完成,如果您提供了两个参数而不是一个,那么第一个函数将被重复调用,直到函数的返回值达到sentinel值:

for x in iter(foo, 0): 
    print x 

这里是迭代工具的解决方案可能是什么样子,iter()绝对是清洁的,但是这使您可以测试任何falsy回报:

from itertools import takewhile, imap, repeat 
for x in takewhile(bool, imap(lambda f: f(), repeat(foo))): 
    print x 
+0

成功!如果第二个参数可能是一个谓词,那将会很好,那么任何falsy值都可以阻止迭代,但是这样做会很好。 – dcrosta 2011-12-20 21:00:43