Sortir de plusieurs boucles for imbriquées en Python
mardi 1 janvier 2013 à 20:27Le mot clé break
permet de sortir d’une boucle for
abruptement. Mais une seule. Parfois on a 3, 4 boucles imbriquées, et on aimerait tellement sortir de toutes d’un coup.
Ce que je vais vous montrer est mal. Mais c’est tellement bon.
# on fait une exception qui hérite de StopIteration car c'est ce qui est utilisé # de toute façon pour arrêter une boucle class MultiStopIteration(StopIteration): # la classe est capable de se lever elle même comme exception def throw(self): raise self @contextmanager def multibreak(): # le seul boulot de notre context manager c'est de donne le moyen de lever # l'exception tout en l'attrapant try: yield MultiStopIteration().throw except MultiStopIteration: pass
En gros on se créé un petit context manager, dont le seul but est de créer une exception qui va remonter en pêtant toutes les boucles. Je vous avais dit que c’était mal
Ca s’utilise comme ça:
>>> with multibreak() as stop: ... for x in range(1, 4): ... for z in range(1, 4): ... for w in range(1, 4): ... print w ... if x * z * w == 2 * 2 * 2: ... print 'stop' ... stop() # appel MultiStopIteration().throw() ... 1 2 3 1 2 3 1 2 3 1 2 3 1 2 stop
Je vous avais dit que ça serait bon.
A part le fait que ce n’est pas très rapide au moment du bubbling de l’exception sur 3 blocks, il n’y a aucun danger ou side-effect. On triche en fait à peine, car le mécanisme interne des boucles en Python utilise de toute façon déjà une exception (StopIteration) pour dire à une boucle quand s’arrêter.
Bref, encore une victoire de connard.