Learn python generators by example.
Using generators (generator functions)
>>> def integers(): i = 1 while True: yield i i = i + 1>>> a = integers()>>> next(a)1>>> next(a)2>>> next(a)3>>> next(a)4>>> next(a)5>>>
Assigning a generator to a varialble will automatically create .__next__() or next(generator) method
This will allow you to iterate through the generator values
>>> def yrange(n): i = 0 while i < n: yield i i += 1>>> y = yrange(5)>>> list(y)[0, 1, 2, 3, 4]>>> list(y)[]
You can convert a generator to a list however on the process it will lose its value and transfer it to the list.
>> y = yrange(5)>>> ylist = list(y)>>> ylist[0, 1, 2, 3, 4]>>> ylist[0, 1, 2, 3, 4]>>> list(y)[]
You may assign it to a variable to retain the list. Keep in mind it the original generator will be gone.
>>> def whizbang(): for i in range(10): x = yield i print('i got {}'.format(x))>>> bangbang = whizbang()>>> bangbang.__next__()0>>> next(bangbang)i got None1>>> bangbang.__next__()i got None2>>> next(bangbang)i got None3>>> bangbang.__next__()i got None4
next(generator) is the same as generator.__next__(). Similar to how vars(class) is the same as class.__dict__.
>>> next(bangbang)i got None5
Let’s start sending stuff. Generators have generator.send() method.
>>> bangbang.send('yo')i got yo6>>> bangbang.send('yo yo yo')i got yo yo yo7
In this case bangbang.send’s parameter is assigned to x. Since x = yield i, means x = yield send value and yield i
>>> list(bangbang)i got Nonei got Nonei got None[8, 9]
converting to list is not going to work with .send()
>>> bangbang = whizbang()>>> next(bangbang)0>>> list(bangbang.send('test'))i got testException: TypeError: 'int' object is not iterable---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-1-5e0978d85904> in <module>()----> 1 list(bangbang.send('test'))
TypeError: 'int' object is not iterable>>>
you will need to call next(generator) at least once before doing a generator.send()
>>> bangbang = whizbang()>>> bangbang.send('s')Exception: TypeError: can't send non-None value to a just-started generator---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-1-10a417413dc0> in <module>()----> 1 bangbang.send('s')
TypeError: can't send non-None value to a just-started generator
Cleaning the values inside a generator is useful. For example if your application run into unknownerror and that left your application on a dirty state instead of risk writing a wrong data you can just close the generator early.
>>> bangbang = whizbang()>>> bangbang<generator object whizbang at 0x7f6b1537b288>>>> bangbang.__next__<method-wrapper '__next__' of generator object at 0x7f6b1537b288>>>> bangbang.__next__()0>>> bangbang.__next__()i got None1>>> bangbang.__next__()i got None2>>> bangbang.__next__()i got None3>>> bangbang.__next__()i got None4>>> bangbang.close()>>> bangbang.__next__()Exception: StopIteration: ---------------------------------------------------------------------------StopIteration Traceback (most recent call last)<ipython-input-1-6f12368577ae> in <module>()----> 1 bangbang.__next__()
StopIteration:
As you see above bangbang should iterate until 10 however it stopped at 4 since we called bangbang.close()