问题
I have a generator function generate
which yields 5 random numbers one at a time. I need to be able to generate the numbers in two ways:
- Single generation, which means a single output of
generate
function - Multiple generation, which means multiple execution of
generate
and yielding all the results together as a single (merged) flow
For that I wrote another function get_resource
, which calls generate
either once or using itertools.chain
to run the generators one after another, but transparently to the caller.
My goal is to use get_resource
function and produce the results in the same format (one list of numbers), regardless of single/multiple generations.
import itertools
import random
def get_resource(values=None):
def resource_generator():
if values:
# run a generator for every value
return itertools.chain(generate(value) for value in values)
else:
return generate('meh')
return resource_generator()
def generate(value):
for _ in range(5):
yield random.randint(1, 101)
if __name__ == '__main__':
# list() is used for convenience only,
# I still need the values one by one
print list(get_resource())
print list(get_resource([1, 2, 3]))
It prints:
[63, 22, 87, 2, 54]
[<generator object generate at 0x1089f7640>, <generator object generate at 0x1089f7690>, <generator object generate at 0x1089f76e0>]
While I need it to print:
[63, 22, 87, 2, 54]
[63, 22, 87, 2, 54, 1, 58, 79, 89, 77, 94, 99, 30, 30, 4]
I use python2.7
回答1:
you should use itertools.chain.from_iterable
return itertools.chain.from_iterable(generate(value) for value in values)
回答2:
You can specify generator delegation using yield from
starting with python-3.3+.
def get_resource(values=None):
def resource_generator():
if values:
for value in values:
yield from generate(value)
else:
yield from generate(None)
return resource_generator()
Now,
>>> list(get_resource([1, 2, 3]))
[46, 99, 97, 1, 42, 79, 69, 9, 45, 25, 77, 56, 54, 7, 41]
来源:https://stackoverflow.com/questions/48862536/create-a-generator-that-yields-values-from-any-number-of-inner-generators