Reputation: 945
I understand generator
generates value once at a time, which could save a lot memory and not like list
which stores all value in memory.
I want to know in python
, how yield
knows which value should be returned during the iteration without storing all data at once in memory?
In my understanding, if i want to print 1 to 100
using yield
, it is necessary that yield
needs to know or store 1 to 100
first and then move point one by one to return value ?
If not, then how yield
return value once at a time, but without storing all value in memory?
Upvotes: 3
Views: 2687
Reputation: 155724
Each time a generator yield
s, the stack frame of the generator is saved off inside the generator object, so it can be restored when execution resumes (when the next value is requested).
You can see the structure definition on CPython here.
If you want to see more, generators are somewhat introspectable, so you can take a look at, say, the progression of the locals, the line number it's currently on, etc.:
def myrange(n):
for i in range(n):
yield i
mr = myrange(10)
# Before any values consumed:
print(mr.gi_frame.f_locals) # Outputs {'n': 10}
print(mr.gi_frame.f_lineno) # Outputs 1
next(mr) # Advance one
print(mr.gi_frame.f_locals) # Outputs {'n': 10, 'i': 0}
print(mr.gi_frame.f_lineno) # Outputs 3
list(mr) # Consumes generator
print(mr.gi_frame) # Outputs None; the frame is discarded when the generator finishes
Upvotes: 2
Reputation: 71471
Simply put, yield
delays the execution but remembers where it left off. However, more specifically, when yield
is called, the variables in the state of the generator function are saved in a "frozen" state. When yield
is called again, the built in next
function sends back the data in line to be transmitted. If there is no more data to be yielded (hence a StopIteration
is raised), the generator data stored in its "frozen" state is discarded.
Upvotes: 3