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