J'ai une fonction de générateur comme celle-ci:
def myfunct():
...
yield result
La façon habituelle d'appeler cette fonction serait:
for r in myfunct():
dostuff(r)
Ma question, existe-t-il un moyen d'obtenir un seul élément du générateur quand je le souhaite? Par exemple, j'aimerais faire quelque chose comme:
while True:
...
if something:
my_element = pick_just_one_element(myfunct())
dostuff(my_element)
...
python
iterator
generator
python-2.x
Alexandros
la source
la source
next(gen, default)
peut également être utilisé pour éviter l'StopIteration
exception. Par exemple,next(g, None)
pour un générateur de chaînes, vous obtiendrez soit une chaîne, soit None une fois l'itération terminée.next(g)
. Cela va appeler en interneg.__next__()
, mais vous n'avez pas vraiment à vous en soucier, tout comme vous ne vous souciez généralement paslen(a)
des appels internesa.__len__()
.g.next()
estg.__next__()
en py3k. La fonction intégréenext(iterator)
existe depuis Python 2.6, et c'est ce qui devrait être utilisé dans tout le nouveau code Python, et il est trivial de la réimplémenter si vous devez prendre en charge py <= 2.5.Pour choisir un seul élément d'un générateur à utiliser
break
dans unefor
instruction, oulist(itertools.islice(gen, 1))
Selon votre exemple (littéralement), vous pouvez faire quelque chose comme:
Si vous voulez " obtenir un seul élément du générateur [une fois généré] chaque fois que je le souhaite " (je suppose que 50% c'est l'intention d'origine et l'intention la plus courante) alors:
De cette façon, l'utilisation explicite de
generator.next()
peut être évitée, et la gestion de fin d'entrée ne nécessite pas deStopIteration
gestion d'exceptions (cryptique) ou de comparaisons de valeurs par défaut supplémentaires.La section d'instructions
else:
offor
n'est nécessaire que si vous voulez faire quelque chose de spécial en cas de fin de générateur.Remarque sur
next()
/.next()
:En Python3, la
.next()
méthode a été renommée pour.__next__()
une bonne raison: elle est considérée comme de bas niveau (PEP 3114). Avant Python 2.6, la fonction intégréenext()
n'existait pas. Et il a même été discuté de passernext()
auoperator
module (ce qui aurait été judicieux), en raison de son besoin rare et de l'inflation douteuse des noms intégrés.L'utilisation
next()
sans défaut est toujours une pratique de très bas niveau - jetantStopIteration
ouvertement le cryptique comme un boulon dans le code d'application normal. Et l'utilisationnext()
avec la sentinelle par défaut - qui devrait être la meilleure option pour une entréenext()
directebuiltins
- est limitée et donne souvent raison à une logique / lisibilité non pythonique étrange.Bottom line: L'utilisation de next () devrait être très rare - comme l'utilisation des fonctions du
operator
module. En utilisantfor x in iterator
,islice
,list(iterator)
et d' autres fonctions acceptant un itérateur est en toute transparence la façon naturelle d'utiliser itérateurs au niveau de l' application - et tout à fait toujours possible.next()
est de bas niveau, un concept supplémentaire, non évident - comme le montre la question de ce fil. Tandis que, par exemple, l'utilisationbreak
dansfor
est conventionnelle.la source
mySeq.head
?Je ne pense pas qu'il existe un moyen pratique de récupérer une valeur arbitraire à partir d'un générateur. Le générateur fournira une méthode next () pour se déplacer, mais la séquence complète n'est pas produite immédiatement pour économiser de la mémoire. C'est la différence fonctionnelle entre un générateur et une liste.
la source
Pour ceux d'entre vous qui parcourent ces réponses pour un exemple de travail complet pour Python3 ... et bien voilà:
Cela produit:
la source
Le générateur est une fonction qui produit un itérateur. Par conséquent, une fois que vous avez une instance d'itérateur, utilisez next () pour extraire l'élément suivant de l'itérateur. À titre d'exemple, utilisez la fonction next () pour récupérer le premier élément, puis utilisez-la
for in
pour traiter les éléments restants:la source
assurez-vous d'attraper l'exception levée après la prise du dernier élément
la source
Je crois que la seule façon est d'obtenir une liste de l'itérateur puis d'obtenir l'élément que vous voulez de cette liste.
la source
myfunct()
génère un grand nombre de valeurs) puisque vous pouvez utiliser la fonction intégréenext
pour obtenir la prochaine valeur générée.