Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Iterate" a function's return values

Tags:

python

Suppose I have a function which consults some external stateful service and returns a value from it, for simplicity let's assume the value is an integer:

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

It's clear that I can call this function 9 times before it returns a falsy value (the 10th call will return 0 which will evaluate to false in boolean contexts). With some function that works this way, I can now "iterate" it by wrapping it in a generator:

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

And then:

for x in take_while_truthy(foo):
    print x

gives me:

9
8
[...]
2
1

My question is: is there a higher-order function somewhere in the standard library which does this or something like it? I skimmed itertools and functools but didn't find anything quite like what I want to do. Have I missed something?

like image 505
dcrosta Avatar asked Feb 22 '23 01:02

dcrosta


1 Answers

This can actually be done using the built-in iter(), if you provide two arguments instead of one then the first is expected to be a function that will be called repeatedly until the return value of the function reaches the sentinel value:

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

Here is what the itertools solution might look like, iter() is definitely cleaner but this allows you to test for any falsy return:

from itertools import takewhile, imap, repeat
for x in takewhile(bool, imap(lambda f: f(), repeat(foo))):
    print x
like image 131
Andrew Clark Avatar answered Mar 04 '23 09:03

Andrew Clark