Thèmes liés aux générateurs en Python

PythonPythonBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Cette section présente quelques sujets supplémentaires liés aux générateurs, notamment les expressions de générateur et le module itertools.

Expressions de générateur

Une version génératrice d'une compréhension de liste.

>>> a = [1,2,3,4]
>>> b = (2*x for x in a)
>>> b
<generator object at 0x58760>
>>> for i in b:
...   print(i, end=' ')
...
2 4 6 8
>>>

Différences avec les Compréhensions de liste.

  • Ne construit pas une liste.
  • Son seul usage utile est l'itération.
  • Une fois consommée, ne peut pas être réutilisée.

Syntaxe générale.

(<expression> for i in s if <conditional>)

Elle peut également servir comme argument de fonction.

sum(x*x for x in a)

Elle peut être appliquée à tout itérable.

>>> a = [1,2,3,4]
>>> b = (x*x for x in a)
>>> c = (-x for x in b)
>>> for i in c:
...   print(i, end=' ')
...
-1 -4 -9 -16
>>>

L'utilisation principale des expressions de générateur est dans le code qui effectue un certain calcul sur une séquence, mais n'utilise le résultat qu'une seule fois. Par exemple, supprimer tous les commentaires d'un fichier.

f = open('somefile.txt')
lines = (line for line in f if not line.startswith('#'))
for line in lines:
  ...
f.close()

Avec les générateurs, le code s'exécute plus rapidement et utilise peu de mémoire. C'est comme un filtre appliqué à un flux.

Pourquoi utiliser les générateurs

  • De nombreux problèmes sont bien plus clairs lorsqu'ils sont exprimés en termes d'itération.
    • Parcourir une collection d'éléments et effectuer une opération de quelque type (recherche, remplacement, modification, etc.).
    • Les pipelines de traitement peuvent être appliqués à une large gamme de problèmes de traitement de données.
  • Meilleure efficacité mémoire.
    • Ne produisent des valeurs que lorsqu'elles sont nécessaires.
    • En contraste avec la construction de gigantesques listes.
    • Peuvent fonctionner sur des données en flux
  • Les générateurs encouragent la réutilisation de code
    • Sépare l'itération du code qui utilise l'itération
    • Vous pouvez construire une boîte à outils de fonctions d'itération intéressantes et les combiner.

Module itertools

Le module itertools est un module de bibliothèque avec diverses fonctions conçues pour aider avec les itérateurs/générateurs.

itertools.chain(s1,s2)
itertools.count(n)
itertools.cycle(s)
itertools.dropwhile(predicate, s)
itertools.groupby(s)
itertools.ifilter(predicate, s)
itertools.imap(function, s1,... sN)
itertools.repeat(s, n)
itertools.tee(s, ncopies)
itertools.izip(s1,..., sN)

Toutes les fonctions traitent les données de manière itérative. Elles implémentent divers types de modèles d'itération.

Plus d'informations dans le tutoriel Generator Tricks for Systems Programmers de PyCon '08.

Dans les exercices précédents, vous avez écrit du code qui suivait les lignes écrites dans un fichier de journal et les a analysées en une séquence de lignes. Cet exercice continue sur cette base. Assurez-vous que stocksim.py est toujours en cours d'exécution.

Exercice 6.13 : Expressions de générateur

Les expressions de générateur sont une version génératrice d'une compréhension de liste. Par exemple :

>>> nums = [1, 2, 3, 4, 5]
>>> squares = (x*x for x in nums)
>>> squares
<generator object <genexpr> at 0x109207e60>
>>> for n in squares:
...     print(n)
...
1
4
9
16
25

Contrairement à une compréhension de liste, une expression de générateur ne peut être utilisée qu'une seule fois. Ainsi, si vous essayez une autre boucle for, vous n'obtenez rien :

>>> for n in squares:
...     print(n)
...
>>>

Exercice 6.14 : Expressions de générateur dans les arguments de fonction

Les expressions de générateur sont parfois utilisées dans les arguments de fonction. Cela peut paraître un peu étrange au premier abord, mais essayez cet exemple :

>>> nums = [1,2,3,4,5]
>>> sum([x*x for x in nums])    ## Une compréhension de liste
55
>>> sum(x*x for x in nums)      ## Une expression de générateur
55
>>>

Dans l'exemple ci-dessus, la deuxième version utilisant des générateurs utiliserait beaucoup moins de mémoire si une grande liste était manipulée.

Dans votre fichier portfolio.py, vous avez effectué quelques calculs impliquant des compréhensions de liste. Essayez de les remplacer par des expressions de générateur.

✨ Vérifier la solution et pratiquer

Exercice 6.15 : Simplification du code

Les expressions de générateur sont souvent un remplacement utile pour de petites fonctions génératrices. Par exemple, au lieu d'écrire une fonction comme celle-ci :

def filter_symbols(rows, names):
    for row in rows:
        if row['name'] in names:
            yield row

Vous pourriez écrire quelque chose comme ceci :

rows = (row for row in rows if row['name'] in names)

Modifiez le programme ticker.py pour utiliser des expressions de générateur le cas échéant.

✨ Vérifier la solution et pratiquer

Sommaire

Félicitations ! Vous avez terminé le laboratoire sur les générateurs avancés. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.