web-dev-qa-db-fra.com

Python `for` syntaxe: code de bloc vs expressions de générateur de ligne unique

Je connais la boucle for dans un contexte de bloc-code. par exemple:

for c in "Word":
    print c

Je viens de rencontrer quelques exemples qui utilisent for différemment. Plutôt que de commencer par l'instruction for, ils la taguent à la fin d'une expression (et n'impliquent pas de bloc de code en retrait). par exemple:

sum(x*x for x in range(10))

Quelqu'un peut-il m'indiquer une documentation décrivant cette utilisation de for? J'ai pu trouver des exemples, mais pas des explications. Toute la documentation for que j'ai pu trouver décrit l'utilisation antérieure (exemple de code de bloc). Je ne sais même pas comment appeler cette utilisation, alors je m'excuse si le titre de ma question n'est pas clair.

24
ivan

Ce que vous indiquez est Generator en Python. Jeter un coup d'œil à: -

Voir la documentation: - Generator Expression qui contient exactement le même exemple que vous avez posté

De la documentation: -

Les générateurs sont un outil simple et puissant pour créer des itérateurs. Ils sont écrits comme des fonctions normales mais utilisent la déclaration de rendement chaque fois qu'ils veulent renvoyer des données. À chaque fois que next () est appelé, le fichier le générateur reprend là où il avait été laissé (il se souvient de toutes les valeurs de données .__ et de la dernière instruction exécutée)

Les générateurs sont similaires à List Comprehension que vous utilisez avec square brackets au lieu de brackets, mais ils utilisent davantage la mémoire. Ils ne renvoient pas la list complète du résultat en même temps, mais ils renvoient un objet générateur. Chaque fois que vous appelez next() sur l'objet generator, le générateur utilise yield pour renvoyer la valeur suivante.

List Comprehension pour le code ci-dessus ressemblerait à ceci: -

[x * x for x in range(10)]

Vous pouvez également ajouter des conditions pour filtrer les résultats à la fin du for.

[x * x for x in range(10) if x % 2 != 0]

Cela retournera une liste de numbers multipliée par 2 dans l'intervalle 1 à 5, si le nombre n'est pas divisible par 2.

Un exemple de Generators illustrant l'utilisation de yield peut être: -

def city_generator():
    yield("Konstanz")
    yield("Zurich")
    yield("Schaffhausen")
    yield("Stuttgart")

>>> x = city_generator()
>>> x.next()
Konstanz
>>> x.next()
Zurich
>>> x.next()
Schaffhausen
>>> x.next()
Stuttgart
>>> x.next()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
StopIteration

Donc, vous voyez que chaque appel à next() exécute la prochaine yield() dans generator. et à la fin il jette StopIteration.

24
Rohit Jain

Ce sont des expressions génératrices et elles sont liées à compréhensions de liste

La compréhension des listes permet de créer facilement des listes. Par exemple, si vous voulez créer une liste de carrés parfaits, procédez comme suit:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Mais au lieu de cela, vous pouvez utiliser une liste de compréhension:

squares = [x**2 for x in range(10)]

Les expressions de générateur sont similaires à la compréhension de liste, sauf qu'elles renvoient un objet générateur au lieu d'une liste. Vous pouvez effectuer une itération sur cet objet générateur de la même manière que pour une liste de compréhensions, mais vous n'avez pas à stocker la liste entière en mémoire en une fois, comme vous le feriez si vous créiez la liste dans une liste de compréhension.

6
Matt

Votre exemple spécifique s'appelle une expression generator . Les compréhensions de liste , les compréhensions de dictionnaire et les compréhensions de set ont une signification similaire (différents types de résultats et expressions de générateur sont paresseux) et ont la même syntaxe, modulo étant entre autres types de crochets et dans le cas d'une compréhension dictée ayant expr1: expr2 au lieu d'une seule expression (x * x dans votre exemple).

0
user395760

La documentation pour les expressions du générateur est ici https://www.python.org/dev/peps/pep-0289/ Voici le code utilisant l'expression du générateur.

list(x**2 for x in range(0,10))
0
Saurabh