Le générateur Python est utile, mais une fois que vous l'utilisez dans une instruction for pour une boucle, vous essayez de l'utiliser à nouveau dans une instruction for, cela ressemble à un carappo.
def i(n):
yield n + 1
yield n + 2
g = i(10)
print('first time:')
for n in g:
print(n)
print('second time:')
for n in g:
print(n)
La sortie est
first time:
11
12
second time:
Ce sera. Aucun élément n'a été itéré dans la deuxième boucle «for».
Dans les situations où vous voulez que «11» et «12» reviennent dans la deuxième boucle «for» et les suivantes, les techniques suivantes ont fonctionné.
class ReiteratableWrapper(object):
def __init__(self, f):
self._f = f
def __iter__(self):
return self._f()
def i(n):
yield n + 1
yield n + 2
import functools
f = functools.partial(i, 10)
g2 = ReiteratableWrapper(f)
for n in g2:
print(n)
for n in g2:
print(n)
La classe ReiteratableWrapper
prend une fonction de générateur. Puisqu'il est appelé sans donner d'argument en interne, si vous voulez faire un appel de générateur avec un argument, créez une fonction sans argument qui lie l'argument en utilisant la fonction functools.partial
etc. comme dans l'exemple.
Les expressions évaluées dans le contexte après in dans l'instruction for sont appelées la méthode __iter__
.
Par conséquent, une instance de Reiteratable Wrapper
créera automatiquement un nouveau générateur à chaque fois.
Cependant, chaque fois que la méthode __iter__
est évaluée, la fonction de générateur est évaluée et exécutée, donc s'il y a un effet secondaire lors de l'appel de la fonction de générateur tel qu'une limite sur le nombre de fois où la fonction de générateur peut être exécutée, elle ne peut pas être utilisée à plusieurs reprises. Je pense qu'il y a quelque chose.
Je pense que la technique introduite cette fois-ci est efficace pour le contenu qui peut être répété, comme la lecture d'un fichier afin d'économiser de la mémoire, l'envoi d'une requête à la base de données à chaque fois et l'itération dans l'ordre.
Recommended Posts