Élément de note Python efficace 16 Envisagez de renvoyer un générateur sans renvoyer une liste

Il s'agit d'un mémo écrit du livre efficace python d'O'Reilly Japan. https://www.oreilly.co.jp/books/9784873117560/ P35~37

** La liste est la plus simple si vous souhaitez renvoyer les résultats dans une séquence **

Prenons le cas de la vérification de la position des caractères vides dans une phrase

def index_words(text):
    result = []
    if text:
        result.append(0)
    for index, letter in enumerate(text):
        if letter == ' ':
            result.append(index + 1)
    return result

address = 'Four score and secer years ago...'
result = index_words(address)
print(result[:3])


>>>
[0, 5, 11]

L'opération elle-même est normale, mais il y a deux problèmes

  1. De nombreux caractères dans le code (redondants)
  2. Génération inutile de liste de résultats

1. De nombreux caractères dans le code (redondants)

Il y a un point qu'il est difficile de lire dans son ensemble en l'ajoutant plusieurs fois avec append dans la définition de la fonction. Il est pratique d'utiliser un générateur dans de tels cas

def index_words_iter(text):
    if text:
        yield 0
    for index, letter in enumerate(text):
        if letter == " ":
            yield index + 1

result = list(index_words_iter(address))
print(result[:3])

>>>
[0, 5, 11]

En utilisant yield, il renvoie un itérateur à chaque fois. Vous pouvez également générer facilement une liste en passant un itérateur à list ().

2. Génération inutile de liste de résultats

La création d'une liste de résultats dans la fonction index_words signifie que la mémoire sera consommée en conséquence. Pour le traitement de données volumineuses, il existe un risque de crash.

À cet égard, le générateur délivre un élément de données à chaque fois, de sorte qu'il peut gérer n'importe quelle longueur. ** Minimiser la consommation de mémoire ** Un générateur qui lit les données d'un fichier et les traite une par une

def index_file(handle):
    offset = 0
    for line in handle:
        if line:
            yield offset
        for letter in line:
            offset += 1
            if letter ==" ":
                yield offset
from itertools import islice
with open("address.txt", "r") as f:
    it = index_file(f)
    results = islice(it, 0, 3)
    print(list(results))

>>>
[0, 5, 11]

Vous pouvez désormais gérer des phrases de n'importe quelle longueur et vous n'avez pas à vous soucier des plantages de mémoire. Cependant, il est important de savoir qu'en raison de la nature des itérateurs et des générateurs, le contenu change à chaque fois qu'ils sont appelés (avec état).

Recommended Posts

Élément de note Python efficace 16 Envisagez de renvoyer un générateur sans renvoyer une liste
Élément de mémo Python efficace 9 Considérons une expression de générateur pour la notation d'inclusion de grande
Élément de mémo Python efficace 3
La liste Python n'est pas une liste
Une note sur [python] __debug__
Point 17 de la note Python efficace Respect de la certitude lors de l'utilisation d'itérateurs pour les arguments
Note Python efficace Item 15 Savoir comment les fermetures sont liées à la portée de la fonction
Obtenez une liste de fichiers dans un dossier avec python sans chemin
Python: une note sur les classes 1 "Résumé"
python / Créer un dict à partir d'une liste.
Précautions lors de la création d'un générateur Python
Une note sur mock (bibliothèque fictive Python)
Élément de mémo Python efficace 4 Écrire une fonction d'aide au lieu d'une expression compliquée
Élément de mémoire Python efficace 7 Utilisez la notation d'inclusion de liste au lieu de la carte et du filtre
Une note où un débutant Python s'est retrouvé coincé
[Python] Comment convertir une liste bidimensionnelle en liste unidimensionnelle
Afficher une liste d'alphabets en Python 3
Notation inclusive de Python (à propos de l'expression de liste et de générateur) [supplémentaire]
Mémo Python efficace Élément 10 Énumérer à partir de la plage
[python] Obtenir une liste de variables d'instance
[Python] Obtenir une liste de dossiers uniquement
EP 16 Envisager un générateur au lieu de renvoyer des listes
Élément de note Python efficace 12 Évitez d'utiliser des blocs else après les boucles for et while