L'itérateur lui-même peut ne pas tourner vers la fin à cause de break
etc., mais il y a de rares cas où vous voulez tourner l'itération à l'intérieur du générateur jusqu'à la fin.
A titre d'exemple, le "range_printsum" suivant ajoute le processus d'impression de la somme de la plage à la fonction "range".
gen.py
def range_printsum(*args, **kwargs):
sum_ = 0
for i in range(*args, **kwargs):
sum_ += i
yield i
print(sum_)
Dans cette implémentation du générateur, si l'itération est arrêtée au milieu, ce qui est réellement stocké dans «sum_» est le nombre total de «yield», et «sum_» n'est pas sorti en premier lieu.
>>> from gen import range_printsum
>>> for i in range_printsum(11):
... pass
...
55
>>> for i in range_printsum(11):
... if i > 5:
... break
...
>>>
Alors capturez Generator Exit
. Ceci est envoyé lorsque le générateur est fermé (lorsque le générateur close ()
est appelé). Cela peut être capturé même si la boucle telle que «for» est interrompue.
Après avoir capturé GeneratorExit
, modifiez range_printsum
pour qu'il ne renvoie pas de valeur et ajoute seulement.
gen.py
def range_printsum(*args, **kwargs):
sum_ = 0
stop_yield = False
for i in range(*args, **kwargs):
sum_ += i
if not stop_yield:
try:
yield i
except GeneratorExit:
stop_yield = True
print(sum_)
Cette fois, cela fonctionne comme prévu.
>>> from gen import range_printsum
>>> for i in range_printsum(11):
... pass
...
55
>>> for i in range_printsum(11):
... if i > 5:
... break
...
55
>>>
Cela fonctionne même s'il est interrompu comme ça.
>>> try:
... for i in range_printsum(11):
... if i > 5:
... raise IndexError
... except IndexError:
... pass
...
55
>>>
Pour mettre en garde les spécifications du générateur, un générateur une fois fermé ne doit pas générer de valeur. Si vous «donnez» une valeur après avoir capturé le «GeneratorExit», vous obtiendrez l'erreur «RuntimeError: generator ignored GeneratorExit».
Recommended Posts