I have a Python generator that can call itself to get more elements to yield. It looks like this:
def gen(list):
# ...
if list:
for x in gen(list[1:]):
yield x
My question is about the last two lines: is there a more concise way to express this? I am hoping for something like this (understanding this isn't valid Python as-is):
def gen(list):
# ...
if list:
yield each in gen(list[1:])
Python 3.3 added the yield from keyword. Here's a comparison between what you currently have and code using the new keyword:
yield_from_test.py:
def gen_for(a_list):
if a_list:
yield a_list[0]
for x in gen_for(a_list[1:]):
yield x
def gen_yield(a_list):
if a_list:
yield a_list[0]
yield from gen_yield(a_list[1:])
if __name__ == '__main__':
assert list(gen_for([1,2,3])) == list(gen_yield([1,2,3]))
print(list(gen_yield([1,2,3])))
» python3 yield_from_test.py
[1, 2, 3]
There's been some call for a yield from or the like that "passes through" all the values returned by a subgenerator. See PEP 380 for some ideas that have been bounced around. However, nothing has been implemented yet. Your first example is correct.
Your code sample is very idiomatic and concise, no need and no real chance for further improvements and especially not when it comes at readability.
Your first example is the proper solution.
来源:https://stackoverflow.com/questions/6257644/python-generator-to-yield-everything-from-another-generator-call