Reputation: 1525
Is is possible in Python to have a generator that yields values in a loop be alternatively called as a normal function where the final value of that loop is returned? I tried setting a flag as argument and then choose to yield or return depending on that flag. But the mere existence of the keyword yield in a function transforms it automatically into a generator and Python complains that there was a return statement in a generator.
Here an example of such a function:
def function(generator=True):
a = 0
for i in range(10):
a = i
if generator:
yield a
if not generator:
return a
Such a function would be useful for me when in some cases I just need the final result (eg. using it as residual function for optimization) while in other cases I need the incremental results after each iteration (for example using a differential model for a robot, updating the robot's pose with each new velocity command). For now I am having two functions where one has the yield and the other has the return. So is it possible to combine those two?
Upvotes: 0
Views: 318
Reputation: 5322
it's still a generator, even calling return. I'd to not mix both generator/regular function anyway.
You can wrap something on top of the iterator, in case you need to loop through the results anyway.
A simple code that could do what you want:
last = None
for last in function(): pass
Now last holds the value you want and you can use it on your code.
The return inside a generator was added to Python 3.3 And it's equivalent to StopIteration(value)
return expr in a generator causes StopIteration(expr) to be raised upon exit from the generator.
In a generator, the statement
return value is semantically equivalent to
raise StopIteration(value) except that, as currently, the exception cannot be caught by except clauses within the returning generator.
Upvotes: 1
Reputation: 49330
You'll still have to iterate over it to get its single value, but you can use yield
again instead of return
to accomplish this.
>>> def function(generator=True):
... a = 0
... for i in range(10):
... a = i
... if generator:
... yield a
... if not generator:
... yield a
...
>>> a = function()
>>> print(*a)
0 1 2 3 4 5 6 7 8 9
>>> a = function(0)
>>> print(a)
<generator object function at 0x0000000001603240>
>>> print(*a)
9
>>> a = function(0)
Note that having return
inside a generator is a SyntaxError
in Python 2, but not Python 3. Replacing the return
with yield
produces the same result in 2 and 3.
Upvotes: 1