In C würde dies einen Überlauf verursachen und nicht zu "unendlich" gehen
Philipp
1
Sollte der Titel dieser Frage nicht in "Schleifen von 0 nach unendlich in Python" geändert werden? Sie versuchen einfach, ein "Unendliches range" zu haben, damit Sie vermeiden könnenwhile True: i += 1
Dies spielt auch gut mit takewhile:for x in takewhile(thereIsAReasonToContinue, count()):
Georg
Für mich for i in range(sys.maxint)bricht mit einem MemoryError. Sie haben auch erwähnt, xrange()was funktioniert.
Scai
3
@scai rangeersetzt in Python3 Python2 xrange. In Python2 rangewird eine tatsächliche Liste von Ints erstellt und zurückgegeben. Sie werden nicht genug RAM für eine so große Liste haben
John La Rooy
17
defto_infinity():
index = 0whileTrue:
yield index
index += 1for i in to_infinity():
if i > 10:
break
i = 0whilenot 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 iden Ablauf der Schleife nicht wie in C beeinflusst. Daher ist die Verwendung einer whileSchleife die geeignetere Wahl, um diesen C-Code nach Python zu portieren.
from itertools import takewhile, count
defthereIsAReasonToContinue(i):returnnot 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
takewhileimitiert 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 iim 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.
Danke, das war es, wonach ich gesucht habe. Sauberster und schönster Ansatz imo.
Marcel Braasch
Ja, sehr sauber, ich hatte die Leistung yieldanderer als für Lazy-Sequence-Generatoren nicht ganz ausgeschöpft , aber ein Freund hat sie kürzlich verwendet, um eine pushd/popdFunktion bereitzustellen , ohne einen expliziten Stack verwalten zu müssen. Sehr klug war es.
paxdiablo
2
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 inach dem Ende der Schleife benötigen ):
int i = 0;
while (! thereIsAReasonToBreak(i)) {
// do something
i++;
}
oder (wenn nur die Schleife ierfasst werden kann ):
for (int i = 0; ! thereIsAReasonToBreak(i); ++i) {
// do something
}
Das würde sich in das Python-Äquivalent übersetzen lassen:
i = 0whilenot 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?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()
undxrange()
waren beschränkt aufsys.maxsize
. In Python 3range()
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()
.quelle
takewhile
:for x in takewhile(thereIsAReasonToContinue, count()):
for i in range(sys.maxint)
bricht mit einemMemoryError
. Sie haben auch erwähnt,xrange()
was funktioniert.range
ersetzt in Python3 Python2xrange
. In Python2range
wird eine tatsächliche Liste von Ints erstellt und zurückgegeben. Sie werden nicht genug RAM für eine so große Liste habendef to_infinity(): index = 0 while True: yield index index += 1 for i in to_infinity(): if i > 10: break
quelle
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 einerwhile
Schleife die geeignetere Wahl, um diesen C-Code nach Python zu portieren.quelle
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 Änderni
im Schleifenkörper. Es ist auch möglich, diese zu imitierentakewhile
, wenn der Generator eine lokale Variable schließti
, 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.quelle
def infinity(): i=0 while True: i+=1 yield i for i in infinity(): if there_is_a_reason_to_break(i): break
quelle
yield
anderer als für Lazy-Sequence-Generatoren nicht ganz ausgeschöpft , aber ein Freund hat sie kürzlich verwendet, um einepushd/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.
quelle