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
>>>
Signing a generator to a varialble will automatically create .next() 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 None
1
>>> bangbang.__next__()
i got None
2
>>> next(bangbang)
i got None
3
>>> bangbang.__next__()
i got None
4
next(generator) is the same as generator.next(). Similar to how vars(class) is the same as class.dict.
>>> next(bangbang)
i got None
5
Let's start sending stuff. Generators have generator.send() method.
>>> bangbang.send('yo')
i got yo
6
>>> bangbang.send('yo yo yo')
i got yo yo yo
7
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 None
i got None
i 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 test
Exception: 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 you 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 None
1>>> bangbang.__next__()
i got None
2>>> bangbang.__next__()
i got None
3>>> bangbang.__next__()
i got None
4>>> 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()