In C würde ich Folgendes tun:
int i;
for (i = 0;; i++)
if (thereIsAReasonToBreak(i))
break;
Wie kann ich in Python etwas Ähnliches erreichen?
In C würde ich Folgendes tun:
int i;
for (i = 0;; i++)
if (thereIsAReasonToBreak(i))
break;
Wie kann ich in Python etwas Ähnliches erreichen?
range
" zu haben, damit Sie vermeiden könnenwhile True: i += 1
Antworten:
Verwenden von itertools.count
:
import itertools
for i in itertools.count(start=1):
if there_is_a_reason_to_break(i):
break
In Python 2 range()
und xrange()
waren beschränkt auf sys.maxsize
. In Python 3 range()
kann es viel höher gehen, wenn auch nicht bis ins Unendliche:
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
Es ist also wahrscheinlich am besten zu verwenden count()
.
takewhile
:for x in takewhile(thereIsAReasonToContinue, count()):
for i in range(sys.maxint)
bricht mit einem MemoryError
. Sie haben auch erwähnt, xrange()
was funktioniert.
range
ersetzt in Python3 Python2 xrange
. In Python2 range
wird eine tatsächliche Liste von Ints erstellt und zurückgegeben. Sie werden nicht genug RAM für eine so große Liste haben
Einfachste und beste:
i = 0
while not there_is_reason_to_break(i):
# some code here
i += 1
Es kann verlockend sein, die nächstgelegene Analogie zum in Python möglichen C-Code zu wählen:
from itertools import count
for i in count():
if thereIsAReasonToBreak(i):
break
Beachten Sie jedoch, dass das Ändern i
den Ablauf der Schleife nicht wie in C beeinflusst. Daher ist die Verwendung einer while
Schleife die geeignetere Wahl, um diesen C-Code nach Python zu portieren.
Wiederholung des Kommentars von thg435:
from itertools import takewhile, count
def thereIsAReasonToContinue(i):
return not thereIsAReasonToBreak(i)
for i in takewhile(thereIsAReasonToContinue, count()):
pass # or something else
Oder vielleicht prägnanter:
from itertools import takewhile, count
for i in takewhile(lambda x : not thereIsAReasonToBreak(x), count()):
pass # or something else
takewhile
imitiert eine "gut erzogene" C for-Schleife: Sie haben eine Fortsetzungsbedingung, aber Sie haben einen Generator anstelle eines beliebigen Ausdrucks. Es gibt Dinge, die Sie in einer C for-Schleife tun können, die sich "schlecht verhalten", z. B. das Ändern i
im Schleifenkörper. Es ist auch möglich, diese zu imitieren takewhile
, wenn der Generator eine lokale Variable schließt i
, mit der Sie sich dann anlegen. In gewisser Weise macht die Definition dieses Abschlusses besonders deutlich, dass Sie etwas tun, das möglicherweise mit Ihrer Kontrollstruktur verwirrt.
def infinity():
i=0
while True:
i+=1
yield i
for i in infinity():
if there_is_a_reason_to_break(i):
break
yield
anderer als für Lazy-Sequence-Generatoren nicht ganz ausgeschöpft , aber ein Freund hat sie kürzlich verwendet, um eine pushd/popd
Funktion bereitzustellen , ohne einen expliziten Stack verwalten zu müssen. Sehr klug war es.
Wenn du das in C machst, ist dein Urteil dort genauso trübe wie in Python :-)
Für eine Schleife, die bei einer einfachen Bedingungsprüfung zu Beginn jeder Iteration beendet wird, ist es üblicher (und meiner Meinung nach klarer), dies nur im Schleifenkonstrukt selbst zu tun. Mit anderen Worten, so etwas wie (wenn Sie i
nach dem Ende der Schleife benötigen ):
int i = 0;
while (! thereIsAReasonToBreak(i)) {
// do something
i++;
}
oder (wenn nur die Schleife i
erfasst werden kann ):
for (int i = 0; ! thereIsAReasonToBreak(i); ++i) {
// do something
}
Das würde sich in das Python-Äquivalent übersetzen lassen:
i = 0
while not there_is_a_reason_to_break(i):
# do something
i += 1
Nur wenn Sie irgendwo in der Mitte der Schleife beenden müssen (oder wenn Ihre Bedingung so komplex ist, dass Ihre Schleifenanweisung weitaus weniger lesbar wird), müssen Sie sich Sorgen machen, dass sie unterbrochen wird.
Wenn Ihr potenzieller Ausgang zu Beginn der Schleife einfach ist (wie es hier zu sein scheint), ist es normalerweise besser, den Ausgang in die Schleife selbst zu codieren.
while (true): if reasonneeded(i) break i = i+1
sollte funktionieren?