En C, je ferais ceci:
int i;
for (i = 0;; i++)
if (thereIsAReasonToBreak(i))
break;
Comment puis-je réaliser quelque chose de similaire en Python?
Utilisation de itertools.count
:
import itertools
for i in itertools.count():
if there_is_a_reason_to_break(i):
break
En Python2 xrange()
est limité à sys.maxint, ce qui peut être suffisant pour la plupart des applications pratiques:
import sys
for i in xrange(sys.maxint):
if there_is_a_reason_to_break(i):
break
En Python3, range()
peut aller beaucoup plus haut, mais pas à l'infini:
import sys
for i in range(sys.maxsize**10): # you could go even higher if you really want
if there_is_a_reason_to_break(i):
break
Il est donc préférable d'utiliser count()
.
def to_infinity():
index=0
while 1:
yield index
index += 1
for i in to_infinity():
if i > 10:break
Réitérant le commentaire de thg435:
from itertools import takewhile, count
def thereIsAReasonToContinue(i):
return not thereIsAReasonToBreak(i)
for i in takewhile(thereIsAReasonToContinue, count()):
pass # or something else
Ou peut-être plus concis:
from itertools import takewhile, count
for i in takewhile(lambda x : not thereIsAReasonToBreak(x), count()):
pass # or something else
takewhile
imite un C pour un "bon comportement": vous avez une condition de continuation, mais vous avez un générateur au lieu d'une expression arbitraire. Il y a des choses que vous pouvez faire dans une boucle C for qui sont "mal comportées", comme modifier i
dans le corps de la boucle. Il est possible d'imiter ceux-là aussi en utilisant takewhile
, si le générateur est une fermeture sur une variable locale i
avec laquelle vous jouez. D'une certaine manière, la définition de cette fermeture rend particulièrement évident que vous faites quelque chose de potentiellement déroutant avec votre structure de contrôle.
Le plus simple et le meilleur:
i = 0
while not there_is_reason_to_break(i):
# some code here
i += 1
Il peut être tentant de choisir l'analogie la plus proche du code C possible en Python:
from itertools import count
for i in count():
if thereIsAReasonToBreak(i):
break
Mais attention, la modification de i
n'affectera pas le flux de la boucle comme en C. Par conséquent, l'utilisation d'une boucle while
est en fait un choix plus approprié pour le portage ce code C à Python.
Si vous faites cela en C, alors votre jugement est aussi nuageux que ce serait en Python :-)
La meilleure façon C serait:
int i = 0;
while (! thereIsAReasonToBreak (i)) {
// do something
i++;
}
ou:
int i; // *may* be better inside the for statement to localise scope
for (i = 0; ! thereIsAReasonToBreak (i); i++) {
// do something
}
Cela se traduirait par Python:
i = 0
while not thereIsAReasonToBreak (i):
# do something
i += 1
Ce n'est que si vous avez besoin de quitter quelque part dans le milie de la boucle que vous devez vous soucier de la rupture. Si votre sortie potentielle se trouve au début de la boucle (telle qu'elle semble être ici), il est généralement préférable de coder la sortie dans la boucle elle-même.