Précautions lors de la création d'un générateur Python

À la fin de l'article ci-dessous, j'ai écrit que le générateur devrait être conteneurisé.

Cette fois, je vais expliquer cela.

Tout d'abord, créez un générateur qui génère le nombre de Fibonacci comme auparavant. Dans le commentaire de l'article précédent, on m'a appris une méthode d'écriture sophistiquée, je vais donc l'utiliser.

Python


#Générateur
def fibonacci_generator():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

#Générateur conteneurisé
class FibonacciGenerator(object):
    def __iter__(self):
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a + b

Ceux-ci produisent le même résultat.

Python


for fib in fibonacci_generator():
    if fib > 1000:
        break
    print fib,

print

for fib in FibonacciGenerator():
    if fib > 1000:
        break
    print fib,

résultat


 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

Notez que les deux instructions for ci-dessus ne diffèrent que dans le générateur. Il est fastidieux d'écrire ce code à chaque fois que le générateur change, alors faisons-en une fonction.

Python


def print_fib(fib_iterator, limit = 1000):
    for fib in fib_iterator:
        if fib > limit:
            break
        print fib,
    print

print_fib(fibonacci_generator())
print_fib(FibonacciGenerator())

résultat


 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

C'était chouette de créer une fonction pour recevoir le générateur.

Modifions maintenant cette fonction pour afficher le contenu du générateur deux fois.

Python


def print_fib_twice(fib_iterator, limit = 100):
    print "[1]",
    for fib in fib_iterator:
        if fib > limit:
            break
        print fib,
    print " [2]",
    for fib in fib_iterator:
        if fib > limit:
            break
        print fib,
    print

print_fib_twice(fibonacci_generator())
print_fib_twice(FibonacciGenerator())

résultat


[1] 0 1 1 2 3 5 8 13 21 34 55 89  [2]
[1] 0 1 1 2 3 5 8 13 21 34 55 89  [2] 0 1 1 2 3 5 8 13 21 34 55 89

Comment, le générateur qui n'est pas conteneurisé n'affiche pas le contenu de la deuxième fois. La raison en est que si vous utilisez le générateur tel quel, le même sera réutilisé la première et la deuxième fois. Le générateur conteneurisé créera un nouveau générateur pour chaque boucle. Ceci est facile à comprendre si vous essayez ce qui suit.

Python


def print_fib_twice2(fib_iterator, limit1, limit2):
    print "[1]",
    for fib in fib_iterator:
        if fib > limit1:
            break
        print fib,
    print " [2]",
    for fib in fib_iterator:
        if fib > limit2:
            break
        print fib,
    print

print_fib_twice2(fibonacci_generator(), limit1 = 100, limit2 = 400)
print_fib_twice2(FibonacciGenerator(),  limit1 = 100, limit2 = 400)

résultat


[1] 0 1 1 2 3 5 8 13 21 34 55 89  [2] 233 377
[1] 0 1 1 2 3 5 8 13 21 34 55 89  [2] 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

De cette façon, si le générateur est passé à une fonction qui est utilisée plusieurs fois en interne, cela provoquera une erreur inattendue. Par conséquent, il est généralement plus sûr d'en faire un conteneur.

Au contraire, lors de l'écriture d'une fonction qui reçoit un itérateur, il vaut mieux vérifier si elle est conteneurisée. Vous pouvez déterminer si un itérateur est conteneurisé en appliquant ʻiter () `deux fois et en vérifiant si différents itérateurs sont renvoyés.

Python


def print_fib_twice3(fib_iterator, limit = 100):
    if iter(fib_iterator) is iter(fib_iterator):
        raise TypeError("Must supply a container")

    print "[1]",
    for fib in fib_iterator:
        if fib > limit:
            break
        print fib,
    print " [2]",
    for fib in fib_iterator:
        if fib > limit:
            break
        print fib,
    print

Python


print_fib_twice3(fibonacci_generator())

résultat


TypeError: Must supply a container

Python


print_fib_twice3(FibonacciGenerator())

résultat


[1] 0 1 1 2 3 5 8 13 21 34 55 89  [2] 0 1 1 2 3 5 8 13 21 34 55 89

Cela empêchera tout comportement involontaire.

Enjoy!

Recommended Posts

Précautions lors de la création d'un générateur Python
Précautions lors du décapage d'une fonction en python
Problèmes lors de la création d'un outil de conversion csv-json avec python
Une note lors de la création d'un graphe dirigé à l'aide de Graphviz en Python
[Python] Mémo de création de l'outil de grattage
Précautions à prendre lors de la construction d'un environnement PYTHON
Lors de la création d'une matrice dans une liste
Précautions lors de l'utilisation de phantomjs de python
Précautions lors de l'utilisation de six avec Python 2.5
[Python] Chapitre 03-01 graphiques de tortues (création d'une tortue)
Lors de l'écriture d'un programme en Python
Précautions lors de la création d'un tableau à deux dimensions avec toutes les mêmes valeurs
Créer un fichier power simple avec Python
[Python] Utiliser et et ou lors de la création de variables
Remarques lors de la création d'un environnement avec python
Points à noter lors de la résolution de problèmes DP avec Python
Points à surveiller lors de la création d'un environnement Python sur un Mac
[Python] Fonction de générateur
[Mémo Python] Soyez prudent lors de la création d'un tableau à deux dimensions (liste de listes)
Erreur lors de l'installation d'un module avec Python pip
Argument de variable Python Un mémorandum lors de l'héritage d'une classe définie
Procédure de création d'un LineBot réalisé avec Python
Précautions lors du traitement des structures de contrôle dans Python 2.6
[Python] Précautions lors de l'affectation de valeurs à des tableaux multidimensionnels
Remarque Python: lors de l'attribution d'une valeur à une chaîne
Commandes pour créer un environnement python3 avec virtualenv
Procédure de création d'un environnement d'isolation Python (environnement venv)
Pièges piégés lors de l'exécution d'exécutables Windows Python
Notes sur la création d'un environnement python par les débutants
[Développement Web avec Python] Précautions lors de l'enregistrement des cookies
L'histoire lorsqu'un utilisateur Python passe un fichier JSON
Précautions lors de la création d'une vue qui réduit les enregistrements par date et heure
Algorithme A * (édition Python)
Je veux répéter plusieurs fois un générateur Python
[Python] Prenez une capture d'écran
Précautions à prendre lors de la manipulation de Luigi
Essayez de créer un fichier compressé en utilisant Python et zlib
4. Création d'un programme structuré
expression lambda de python ...
Un mémo pour créer un environnement de développement python avec macOS Catalina
Un mémorandum lors de l'écriture de code expérimental ~ Se connecter en python
Précautions lors de l'installation d'un répertoire d'inclusion hiérarchique avec waf
Précautions lors du traitement du type ROS MultiArray en Python
Conseils et précautions lors du portage des programmes MATLAB vers Python
Démoniser un processus Python
Création d'outils de grattage
Choses à noter lors de l'initialisation d'une liste en Python
Que contient cette variable (lorsque le script Python est en cours d'exécution)
Implémentation d'un générateur en utilisant Python> link> yield et next ()> yield
Utilisez communiquer () lors de la réception de la sortie dans un sous-processus Python
Zundokokiyoshi (générateur) en Python
Précautions lors de l'installation de fbprophet
Créer un environnement Python
Créer un chargeur de jeu de données
Répertoire actuel lors de la création d'un nouveau avec Jupyter