I’m trying to understand how yield works and after I had read this text I believed that it’s quite understandable.
However I still don’t understand what’s the connection between yield and __iter__ because I’ve just found out that this code works:
class Vect():
def __init__(self, *args):
self.__a = list(args)
def print_(self):
print self.__a
def __iter__(self):
yield self.__a
asd = Vect(1,2,3,4,5)
for foo in asd:
print foo
I thought that when I have a generator (a function which returns a single argument at the time but returns as many arguments as it can until it hits the end) yield works like: “OK, let’s return this argument, but maybe we can still return another”. However in my example I don’t have any generator, yield “returns” a list and in some way gets access to list’s iterator. I have absolutely no idea what’s going on.
yieldreturns whatever object is passed to it, even if that object is a sequence or a generator or other iterator. Thus:__iter__is called on an object when an iterator over the object’s contents is required (as in a when it is part of afor x in objconstruct). You can useyieldto create a generator (since generators are iterators), but in the present example you don’t need to. The following will work as well:If you want to use
yield, and you want the iterator forVectobjects to move through the contents of the vector, you have to yield each value separately:The
yieldmeans that__iter__will return a generator, and callingnext()on the generator object will resume the function at the point where it last left off, as it iterates through__a.=======
In response to the additional question about how Python tracks where in the execution of the generator it is, I believe it uses the f_lasti (== “last instruction”) of the gi_frame attribute of the generator (Generators, unlike ordinary functions, carry a frame of execution around with them). Here’s a bit of tooling around that shows how the values change:
Note how the f_lasti value corresponds to the numbered line in the disassembled code that that the last yield was on: it restarts from that point when the generator is reentered.