To put it simply, the generator function feels like a return can be created in the middle of the function.
However, the feature is that it does not end even if you do something like return.
Also, I will return them one by one, so I don't use much memory.
I will also explain the sub-generator added in python3.
Code created this time: https://github.com/KodairaTomonori/Qiita/tree/master/default_module/syntax
Actually use yield instead of return.
First of all, simply from the counter and fibonatti sequence generation functions that count numbers
counter_and_fibonati.py
def counter():
num = 0
while True:
yield num
num += 1
def fibonatti():
now = 0
next_num = 1
while True:
yield now
now, next_num = next_num, now + next_num
if __name__ == '__main__':
count = counter()
print('print 0-3, for i in count')
for i in count:
print(i, end=', ')
if i >= 3:
print()
break
print('next_count, count.__next__()')
print(count.__next__())
print('print 5-7, for i in count')
for i in count:
print(i, end=', ')
if i >= 7:
count.close()
print()
print('print fibonatti')
for i in fibonatti():
if i > 100: break
print(i, end=', ')
print(i)
print 0-3, for i in count 0, 1, 2, 3, next_count, count.__next__() 4 print 5-7, for i in count 5, 6, 7, print fibonatti 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144
First, the counter function is simple, starting at num = 0 and entering an infinite loop of while.
Returns num with yield num for each loop.
Then was counter called? Sometimes num + 1 and then yield num is returned.
Each time it is called, a + 1 value is returned.
When using it, it is written in the place of main, but if you put it in the for statement, it will return the value 0,1,2,3 in sequence for each loop.
You can save its state (num) by defining it as a variable withcount = counter ().
Using count.__next__ () will return the next number, that is, 4.
The following for statement also adds one by one and returns it as before.
However, unlike before, the state of count stops at num = 4, so this loop starts at 5.
So, at the end, when it became 7 or more, I didcount.close ()to end the loop.
If you use .close (), you can exit the for statement and lose the function as a generator of count.
After this, spit out count.__next__ () and StopIteration.
The fibonatti is almost the same, so there is no particular problem.
In this case, the generator is placed directly with fibonatti (), so after exiting the for statement, the generator where now, next_num is stored will go somewhere.
The fact that it can be turned with a for statement can be made into a list by enclosing it in list (), but in that case, if you do not set a limit in the generator function, you will die in an infinite loop, so be careful.
You can pass arguments each time with .send (x).
.send (x) gives x to the position of yield, so you have to execute.__ next__ ()once.
generator_send.
def generator(step):
val = 0
prev = 0
while True:
if step == None:
step = prev
prev = step
val += step
step = yield val
if __name__ == '__main__':
gen = generator(0)
print(gen.__next__(), end=', ')
for i in [1,2,3,4,5,6]:
print(gen.send(i) , end=', ')
print()
0, 1, 3, 6, 10, 15, 21,
The generator function is a program that adds the received argument step to val.
First, set the generator (0) initial value to 0.
Then use .__next__ () to go to step = yield val.
Then 0 will be returned.
Then enter the for statement and turn from 1 to 6.
When gen.send (i) is executed, ʻi is entered at the previous step = yield val. In other words, if you do gen.send (i), you get step = i. I will loop like that. Here, if you do .__ next __ ()without using.send (), you will get step = None`.
The sub-generator will execute the generator if you do yield from generator.
generator is a generator function.
This makes recursion very convenient.
A sample program for generating permutations containing the same is explained.
ex_permutation.py
def ex_permutation(iterable, now_list=[]):
if not iterable:
yield now_list
return
for i in [iterable.index(i) for i in set(iterable) ]:
yield from permutation(iterable[:i] + iterable[i+1:], now_list + [iterable[i] ])
if __name__ == '__main__':
permu = ex_permutation([2,2,3])
for i in permu:
print(i)
[2, 2, 3] [2, 3, 2] [3, 2, 2]
I don't care what's inside, but I'm just doing it recursively using set () so that it doesn't get covered.
So you can write recursively with yield from.
Finally, it returns now_list when the contents of ʻiterable` are empty.
I don't know what it is, but it's convenient!
It seems to be confusing without this.
You can return a value in the middle of the function with yield.
You can end the generator function with .close ().
Do the following with .__next__ ()
You can pass a value with .send ()
yield from is convenient.
Recommended Posts