web-dev-qa-db-fra.com

Boucle de 1 à l'infini en Python

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?

47
user2058002

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().

93
John La Rooy
def to_infinity():
    index=0
    while 1:
        yield index
        index += 1

for i in to_infinity():
    if i > 10:break
11
spicavigo

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.

4
Steve Jessop

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.

4
wim

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.

2
paxdiablo