Below is a generator function.
def f(): x=1 while 1: y = yield x x += y
Does this generator function (f
) get implemented, internally, as shown below?
class f(collections.Iterable): def __init__(self): self.x = 1 def __iter__(self): return iter(self) def __next__(self): return self.x def send(self, y): self.x += y return self.next()
Edit:
This is the answer for my question.
Advertisement
Answer
Internally, a generator works about the same as a regular function call. Under-the-hood, running generators and running functions use mostly the same machinery.
When you call either a function or a generator, a stackframe is created. It has the local variables (including the arguments passed into the function), a code pointer to the active opcode, and a stack for pending try-blocks, with-blocks, or loops.
In a regular function, execution begins immediately. When return
is encountered, the final result is kept and the stackframe is freed along with everything it referenced.
In a generator function, the stackframe is wrapped in a generator-iterator object and returned immediately. The code in the generator function only runs when called by next(g)
or g.send(v)
. Execution is suspended when yield
is encountered.
One way to think of generators is that they are like functions that can be paused with yield
and resumed with g.next()
. The stackframe is kept alive, so resuming a running generator is much cheaper than making a new function call which has to build a new frame on every invocation.