I would like you to consider the following code:
def func(alist):
if len(alist) == 1:
return alist[0] * 2
for item in alist:
yield item * 2
When I run func([1])
, I don't get 2
:
>>> func([1])
<generator object func at 0x7f0b9d09c660>
On Python 2, it doesn't even compile:
SyntaxError: 'return' with argument inside generator
Now, I realize that I cannot do this. However, I would like to know why. What exactly is going on behind the scenes that is causing Python to not give me 2
?
Python has to decide whether a function is a generator at bytecode compilation time. This is because the semantics of generators say that none of the code in a generator function runs before the first next
call; the generator function returns a generator iterator that, when next
is called, runs the generator code. Thus, Python can't decide whether a function should be a generator or not by running it until it hits a yield
or a return
; instead, the presence of a yield
in a function signals that the function is a generator.
On Python 3, this isn't a SyntaxError any more, but your function is still unconditionally a generator function. return
with an argument just means something in a generator now, instead of being a syntax error - it determines what yield from
over the generator will return. Iterating over func([1])
will produce no elements, since the generator never yield
s.