Comprenez-vous les compréhensions de listes? Si tel est le cas, une expression de générateur est comme une compréhension de liste, mais au lieu de trouver tous les éléments qui vous intéressent et de les regrouper dans une liste, elle attend et renvoie chaque élément de l'expression, un par un.
>>> my_list =[1,3,5,9,2,6]>>> filtered_list =[item for item in my_list if item >3]>>>print(filtered_list)[5,9,6]>>> len(filtered_list)3>>># compare to generator expression...>>> filtered_gen =(item for item in my_list if item >3)>>>print(filtered_gen)# notice it's a generator object<generator object <genexpr> at 0x7f2ad75f89e0>>>> len(filtered_gen)# So technically, it has no lengthTraceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'generator' has no len()>>># We extract each item out individually. We'll do it manually first....>>> next(filtered_gen)5>>> next(filtered_gen)9>>> next(filtered_gen)6>>> next(filtered_gen)# Should be all out of items and give an errorTraceback(most recent call last):File"<stdin>", line 1,in<module>StopIteration>>># Yup, the generator is spent. No values for you!...>>># Let's prove it gives the same results as our list comprehension...>>> filtered_gen =(item for item in my_list if item >3)>>> gen_to_list = list(filtered_gen)>>>print(gen_to_list)[5,9,6]>>> filtered_list == gen_to_list
True>>>
Étant donné qu'une expression de générateur ne doit produire qu'un seul élément à la fois, cela peut entraîner d'importantes économies dans l'utilisation de la mémoire. Les expressions de générateur ont le plus de sens dans les scénarios où vous devez prendre un élément à la fois, effectuer de nombreux calculs en fonction de cet élément, puis passer à l'élément suivant. Si vous avez besoin de plus d'une valeur, vous pouvez également utiliser une expression de générateur et en saisir quelques-unes à la fois. Si vous avez besoin de toutes les valeurs avant de poursuivre votre programme, utilisez plutôt une compréhension de liste.
Une question ici. J'ai utilisé next (gen_name) pour obtenir le résultat et cela a fonctionné en Python 3. Y a-t-il un scénario spécifique où nous devons utiliser __next __ ()?
Ankit Vashistha
2
@AnkitVashistha Non, utilisez toujours à la next(...)place de .__next__()Python 3.
Todd Sewell
@gotgenes @AnkitVashistha If you need more than one value, you can also use a generator expression and grab a few at a time. Pourriez-vous s'il vous plaît donner un exemple de cette utilisation? Merci.
LittleZero
19
Une compréhension de générateur est la version paresseuse d'une compréhension de liste.
C'est comme une compréhension de liste sauf qu'elle renvoie un itérateur au lieu de la liste, c'est-à-dire un objet avec une méthode next () qui donnera l'élément suivant.
Si vous n'êtes pas familier avec les compréhensions de listes, voir ici et pour les générateurs, voir ici .
La compréhension de liste / générateur est une construction que vous pouvez utiliser pour créer une nouvelle liste / générateur à partir d'un existant.
Supposons que vous souhaitiez générer la liste des carrés de chaque nombre de 1 à 10. Vous pouvez le faire en Python:
>>>[x**2for x in range(1,11)][1,4,9,16,25,36,49,64,81,100]
ici, range(1,11)génère la liste [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], mais la rangefonction n'est pas un générateur avant Python 3.0, et donc la construction que j'ai utilisée est une compréhension de liste.
Si je voulais créer un générateur qui fasse la même chose, je pourrais le faire comme ceci:
>>>(x**2for x in xrange(1,11))<generator object at 0x7f0a79273488>
En Python 3, cependant, il rangey a un générateur, donc le résultat ne dépend que de la syntaxe que vous utilisez (crochets ou crochets).
C'est faux. Le fait que l'expression externe soit un générateur n'a rien à voir avec le fait que l'expression interne l'est ou non. Bien que, de toute évidence, il n'y ait généralement pas beaucoup d'intérêt à ce qu'une expression de générateur prenne des éléments d'une liste, vous pouvez le faire.
Antimoine
Cela peut-il être réécrit plus clairement? Je comprends ce que vous dites, mais comme le dit Antimoine, il semble que vous disiez autre chose. (et ce que vous dites est faux)
Lyndon White
3
La compréhension des générateurs est un moyen simple de créer des générateurs avec une certaine structure. Disons que vous voulez ungenerator qui sort un par un tous les nombres pairs your_list. Si vous le créez en utilisant le style de fonction, ce serait comme ceci:
def allEvens( L ):for number in L:if number %2is0:yield number
evens = allEvens( yourList )
Vous pouvez obtenir le même résultat avec cette expression de compréhension du générateur:
evens =( number for number in your_list if number %2==0)
Dans les deux cas, lorsque vous appelez, next(evens)vous obtenez le numéro pair suivant your_list.
La compréhension du générateur est une approche pour créer des itérables, quelque chose comme un curseur qui se déplace sur une ressource. Si vous connaissez le curseur mysql ou le curseur mongodb, vous savez peut-être que toutes les données réelles ne sont jamais chargées dans la mémoire à la fois, mais une à la fois. Votre curseur se déplace d'avant en arrière, mais il y a toujours un élément d'une ligne / liste en mémoire.
En bref, en utilisant la compréhension des générateurs, vous pouvez facilement créer des curseurs en python.
Réponses:
Comprenez-vous les compréhensions de listes? Si tel est le cas, une expression de générateur est comme une compréhension de liste, mais au lieu de trouver tous les éléments qui vous intéressent et de les regrouper dans une liste, elle attend et renvoie chaque élément de l'expression, un par un.
Étant donné qu'une expression de générateur ne doit produire qu'un seul élément à la fois, cela peut entraîner d'importantes économies dans l'utilisation de la mémoire. Les expressions de générateur ont le plus de sens dans les scénarios où vous devez prendre un élément à la fois, effectuer de nombreux calculs en fonction de cet élément, puis passer à l'élément suivant. Si vous avez besoin de plus d'une valeur, vous pouvez également utiliser une expression de générateur et en saisir quelques-unes à la fois. Si vous avez besoin de toutes les valeurs avant de poursuivre votre programme, utilisez plutôt une compréhension de liste.
la source
next(...)
place de.__next__()
Python 3.If you need more than one value, you can also use a generator expression and grab a few at a time
. Pourriez-vous s'il vous plaît donner un exemple de cette utilisation? Merci.Une compréhension de générateur est la version paresseuse d'une compréhension de liste.
C'est comme une compréhension de liste sauf qu'elle renvoie un itérateur au lieu de la liste, c'est-à-dire un objet avec une méthode next () qui donnera l'élément suivant.
Si vous n'êtes pas familier avec les compréhensions de listes, voir ici et pour les générateurs, voir ici .
la source
La compréhension de liste / générateur est une construction que vous pouvez utiliser pour créer une nouvelle liste / générateur à partir d'un existant.
Supposons que vous souhaitiez générer la liste des carrés de chaque nombre de 1 à 10. Vous pouvez le faire en Python:
ici,
range(1,11)
génère la liste[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
, mais larange
fonction n'est pas un générateur avant Python 3.0, et donc la construction que j'ai utilisée est une compréhension de liste.Si je voulais créer un générateur qui fasse la même chose, je pourrais le faire comme ceci:
En Python 3, cependant, il
range
y a un générateur, donc le résultat ne dépend que de la syntaxe que vous utilisez (crochets ou crochets).la source
La compréhension des générateurs est un moyen simple de créer des générateurs avec une certaine structure. Disons que vous voulez un
generator
qui sort un par un tous les nombres pairsyour_list
. Si vous le créez en utilisant le style de fonction, ce serait comme ceci:Vous pouvez obtenir le même résultat avec cette expression de compréhension du générateur:
Dans les deux cas, lorsque vous appelez,
next(evens)
vous obtenez le numéro pair suivantyour_list
.la source
La compréhension du générateur est une approche pour créer des itérables, quelque chose comme un curseur qui se déplace sur une ressource. Si vous connaissez le curseur mysql ou le curseur mongodb, vous savez peut-être que toutes les données réelles ne sont jamais chargées dans la mémoire à la fois, mais une à la fois. Votre curseur se déplace d'avant en arrière, mais il y a toujours un élément d'une ligne / liste en mémoire.
En bref, en utilisant la compréhension des générateurs, vous pouvez facilement créer des curseurs en python.
la source
Un autre exemple de compréhension du générateur:
la source