[PYTHON] Comment utiliser le générateur

Générateur

Pour faire simple, la fonction de générateur donne l'impression qu'un «retour» peut être créé au milieu de la fonction. Cependant, la caractéristique est que cela ne se termine pas même si vous faites quelque chose comme return. Aussi, je vais les retourner un par un, donc je n'utilise pas beaucoup de mémoire. Je vais également expliquer les sous-générateurs ajoutés dans python3. Code créé cette fois-ci: https://github.com/KodairaTomonori/Qiita/tree/master/default_module/syntax En fait, utilisez «yield» au lieu de «return». Tout d'abord, simplement à partir des fonctions de génération de séquence counter et fibonatti qui comptent

Utilisation de base (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)

production

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

Commentaire

Premièrement, la fonction counter est simple, commençant par num = 0 et entrant dans la boucle infinie while. Renvoie «num» avec «yield num» pour chaque boucle. Puis a été appelé «compteur»? Parfois, «num + 1», puis «yield num» est renvoyé. Chaque fois qu'il est appelé, une valeur «+ 1» est renvoyée. Lors de son utilisation, il est écrit à la place de main, mais si vous le mettez dans l'instruction for, il renverra la valeur 0,1,2,3 séquentiellement pour chaque boucle.

Vous pouvez enregistrer son état (num) en le définissant comme une variable avec count = counter ().

Utiliser count .__ next__ () retournera le numéro suivant, c'est-à-dire 4.

L'instruction for suivante sera également renvoyée une par une de la même manière qu'auparavant. Cependant, contrairement à avant, l'état de count s'arrête à num = 4, donc cette boucle commence à 5. Donc, à la fin, quand il est devenu «7» ou plus, j'ai fait «count.close ()» pour terminer la boucle.

Si vous utilisez .close (), vous pouvez quitter l'instruction for et perdre la fonction en tant que générateur de count. Après cela, crachez count .__ next__ () et StopIteration.

Le «fibonatti» est presque le même, donc il n'y a pas de problème particulier. Ici, puisque le générateur est placé directement avec fibonatti (), le générateur où now, next_num est sauvegardé ira quelque part après avoir quitté l'instruction for.

Le fait qu'il puisse être transformé avec une instruction for peut être transformé en une liste en l'enfermant dans list (), mais dans ce cas, si vous ne définissez pas de limite dans la fonction générateur, vous mourrez dans une boucle infinie, alors soyez prudent.

Lorsque vous voulez donner un argument à chaque fois que vous appelez

Vous pouvez passer un argument à chaque fois avec .send (x). Puisque .send (x) donne x à la position de yield, vous devez exécuter` .__ next__ () ʻune fois.

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

production

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

Commentaire

La fonction generator est un programme qui ajoute l'argument reçu step à val. Tout d'abord, définissez la valeur initiale de générateur (0) sur 0. Utilisez ensuite .__ next__ () pour aller à step = yield val. Ensuite, «0» sera renvoyé. Entrez ensuite l'instruction for et passez de «1 à 6». Lorsque gen.send (i) est exécuté, ʻi est entré à l'étape précédente = yield val. En d'autres termes, si vous faites gen.send (i), vous obtenez step = i. Je vais faire une boucle comme ça. Ici, si vous faites .__ next __ () sans utiliser .send (), vous obtiendrez step = None.

Nouveau dans python3: sous-générateur

Le sous-générateur exécutera le générateur si vous faites rendement du générateur. «générateur» est une fonction de générateur. Cela rend la récurrence très pratique.

Un exemple de programme pour générer une séquence contenant la même séquence est présenté ci-dessous.

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)

production

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

Commentaire

Je me fiche de ce qu'il y a à l'intérieur, mais je le fais juste récursivement en utilisant set () pour qu'il ne soit pas couvert. Vous pouvez donc écrire récursivement avec yield from. Enfin, il retourne now_list lorsque le contenu de ʻiterable` est épuisé. Je ne sais pas ce que c'est, mais c'est pratique! Sans cela, cela semble déroutant.

Résumé

Vous pouvez renvoyer une valeur au milieu de la fonction avec yield. Vous pouvez terminer la fonction du générateur avec .close (). Faites ce qui suit avec .__ next__ () Vous pouvez passer une valeur avec .send () «rendement de» est pratique.

Recommended Posts

Comment utiliser le générateur
Comment utiliser le décorateur
Comment utiliser la fonction zip
Comment utiliser le module optparse
Comment utiliser le module ConfigParser
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser le pipeline Spark ML
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser Pandas 2
Comment utiliser Virtualenv
Comment utiliser numpy.vectorize
Comment utiliser pytest_report_header
[Linux] Comment utiliser la commande echo
Comment utiliser partiel
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser IPython
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse
Comment utiliser le débogueur IPython (ipdb)
Comment utiliser le retour
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
Comment utiliser la bibliothèque C en Python
Comment utiliser MkDocs pour la première fois
Comment utiliser la bibliothèque de dessins graphiques Bokeh
Comment utiliser l'API Google Cloud Translation
Comment utiliser l'API du guide des programmes NHK
[Algorithm x Python] Comment utiliser la liste
Comment utiliser Qt Designer
Comment utiliser la recherche triée
[gensim] Comment utiliser Doc2Vec
python3: Comment utiliser la bouteille (2)
Comprendre comment utiliser django-filter
[Python] Comment utiliser la liste 1
Comment utiliser FastAPI ③ OpenAPI
Comment utiliser Python Argparse
Comment utiliser IPython Notebook
Comment utiliser Pandas Rolling
[Note] Comment utiliser virtualenv
Comment utiliser les dictionnaires redis-py
Python: comment utiliser pydub