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:])
The Yield keyword in Python is similar to a return statement used for returning values or objects in Python. However, there is a slight difference. The yield statement returns a generator object to the one who calls the function which contains yield, instead of simply returning a value.
yield in Python can be used like the return statement in a function. When done so, the function instead of returning the output, it returns a generator that can be iterated upon. You can then iterate through the generator to extract items. Iterating is done using a for loop or simply using the next() function.
One interesting thing to note in the above example is that the value of variable n is remembered between each call. Unlike normal functions, the local variables are not destroyed when the function yields. Furthermore, the generator object can be iterated only once.
Python provides a generator to create your own iterator function. A generator is a special type of function which does not return a single value, instead, it returns an iterator object with a sequence of values.
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.
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]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With