[PYTHON] How to use the generator

Generator

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

Basic usage (yield,. \ _ \ _ Next__ (), .close ())

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)

output

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

Commentary

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.

When you want to give an argument each time you call

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()

output

0, 1, 3, 6, 10, 15, 21,

Commentary

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`.

New in python3: Subgenerator

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)

output

[2, 2, 3] [2, 3, 2] [3, 2, 2]

Commentary

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.

Summary

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

How to use the generator
How to use the decorator
How to use the zip function
How to use the optparse module
How to use the ConfigParser module
How to use xml.etree.ElementTree
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use the Spark ML pipeline
How to use Seaboan
How to use image-match
How to use Pandas 2
How to use Virtualenv
How to use numpy.vectorize
How to use pytest_report_header
[Linux] How to use the echo command
How to use partial
How to use Bio.Phylo
How to use the Linux grep command
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
How to use list []
How to use python-kabusapi
How to use OptParse
How to use the IPython debugger (ipdb)
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
How to use the C library in Python
How to use MkDocs for the first time
How to use the graph drawing library Bokeh
How to use the Google Cloud Translation API
How to use the NHK program guide API
[Algorithm x Python] How to use the list
How to use Qt Designer
How to use search sorted
[gensim] How to use Doc2Vec
python3: How to use bottle (2)
Understand how to use django-filter
[Python] How to use list 1
How to use FastAPI ③ OpenAPI
How to use Python argparse
How to use IPython Notebook
How to use Pandas Rolling
[Note] How to use virtualenv
How to use redis-py Dictionaries
Python: How to use pydub