Rahul Sarma Rahul Sarma - 3 months ago 12
Python Question

Maintain generator object across function calls

let me highlight the problem with the following code:

def genny():
yield 1
yield 2
yield 3


def middleman(input_gen=None):
if input_gen:
gen = input_gen
else:
gen = genny()
return [next(gen), gen]

if __name__ == '__main__':
pro_list = middleman()
pro_value = pro_list[0]
print pro_value
pro_gen_id = pro_list[1]
for i in range(2):
pro_list = middleman(pro_gen_id)
pro_value = pro_list[0]
print pro_value


The restriction I have is that the middleman() function cannot be a generator but I need to display all values from the generator genny(). I did this by passing back the generator object to the main() function and then sending that back again to middleman(). Is this the optimum way to do this or are there any better ways?

Answer

It's a bit hard to say without the larger context to which your example (which is understandably a toy example), is referring.

In general, it's perfectly fine to return multiple values from a function (although a tuple or namedtuple are a bit more common).

In your specific case, though, the middelman function simply nexts the generator (either received or internally constructed), then returns both this value and the generator. I don't think there's any advantage to just letting middleman create or return the generator, and let the client code do the next. The following code is equivalent to yours (see it on ideone):

def genny():
    yield 1
    yield 2
    yield 3

def middleman(input_gen=None):
    return genny() if input_gen is None else input_gen

if __name__ == '__main__':
    pro = middleman()
    for e in pro:
        pro = middleman(pro)
        print e

It's objectively shorter, and to me also clearer.

Comments