Ich möchte eine Endlosschleife erstellen, die von 0 bis 100 auf 0 (und so weiter) zählt und nur dann aufhört, wenn ein Konvergenzkriterium in der Schleife erfüllt ist.
for i in range(0, infinity):
for j in range(0, 100, 1):
print(j) # (in my case 100 lines of code)
for j in range(100, 0, -1):
print(j) # (same 100 lines of code as above)
Gibt es eine Möglichkeit, die beiden for-Schleifen über j in eine zu mischen, damit ich nicht den gleichen Code zweimal in die Schleifen schreiben muss?
Verwenden Sie die chain
-Methode von itertools
import itertools
for i in range(0, infinity):
for j in itertools.chain(range(0, 100, 1), range(100, 0, -1)):
print(j) # (in my case 100 lines of code)
Wie von @Chepner vorgeschlagen, können Sie itertools.cycle()
für die Endlosschleife verwenden:
from itertools import cycle, chain
for i in cycle(chain(range(0, 100, 1), range(100, 0, -1))):
....
Neben den anderen Antworten können Sie ein bisschen Mathematik verwenden:
while(True):
for i in range(200):
if i > 100:
i = 200 - i
Hier ist noch eine andere Möglichkeit:
while notConverged:
for i in xrange(-100, 101):
print 100 - abs(i)
Wenn Sie wiederholt Code verwenden, sparen Sie Platz und Aufwand mit einer Funktion:
def function(x, y, x, num_from_for_loop):
# 100 lines of code
while not condition:
for i in range(1, 101):
if condition:
break
function(x, y, z, i)
for i in range(100, 0, -1):
if condition:
break
function(x, y, z, i)
Sie könnten sogar einen while True
verwenden
Wenn Sie Python 3.5 oder höher verwenden, können Sie generisches Entpacken verwenden:
for j in (*range(0, 100, 1), *range(100, 0, -1)):
oder vor Python 3.5 können Sie itertools.chain
verwenden:
from itertools import chain
...
for j in chain(range(0, 100, 1), range(100, 0, -1)):
up = True # since we want to go from 0 to 100 first
while True: #for infinite loop
# For up == True we will print 0-->100 (0,100,1)
# For up == False we will print 100-->0 (100,0,-1)
start,stop,step = (0,100,1) if up else (100,0,-1)
for i in range(start,stop,step):
print(i)
up = not up # if we have just printed from 0-->100 (ie up==True), we want to print 100-->0 next so make up False ie up = not up( True)
# up will help toggle, between 0-->100 and 100-->0
def up_down(lowest_value, highest_value):
current = lowest_value
delta = 1
while True: # Begin infinite loop
yield current
current += delta
if current <= lowest_value or current >= highest_value:
delta *= -1 # Turn around when either limit is hit
Dies definiert einen Generator, der so lange Werte liefert, wie Sie benötigen. Zum Beispiel:
>>> u = up_down(0, 10)
>>> count = 0
>>> for j in u:
print(j) # for demonstration purposes
count += 1 # your other 100 lines of code here
if count >= 25: # your ending condition here
break
0
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4
3
2
1
0
1
2
3
4
Dies ist eher eine partielle Antwort als eine direkte Antwort auf Ihre Frage. Sie können jedoch auch den Begriff der trigonometrischen Funktionen und ihrer Schwingung verwenden, um eine Hin- und Her-Schleife zu imitieren.
Wenn wir eine cos-Funktion mit einer Amplitude von 100 haben, die nach links und nach oben verschoben ist, so dass f(x) = 0
und 0 <= f(x) <= 100
, dann haben wir die Formel f(x) = 50(cos(x-pi)+1)
(Diagramm der Grafik kann gefunden werden hier . Der Bereich ist das, was Sie brauchen, und Schwingung tritt auf, so dass keine Werte negiert werden müssen.
>>> from math import cos, pi
>>> f = lambda x: 50*(cos(x-pi)+1)
>>> f(0)
0.0
>>> f(pi/2)
50.0
>>> f(pi)
100.0
>>> f(3*pi/2)
50.0
>>> f(2*pi)
0.0
Das Problem besteht natürlich darin, dass die Funktion nicht so einfach Ganzzahlenwerte gibt, daher ist es nicht so hilfreich - aber dies kann für zukünftige Leser hilfreich sein, wenn trigonometrische Funktionen für ihren Fall hilfreich sein könnten.
Ich hatte vor einiger Zeit ein ähnliches Problem, bei dem ich auch Werte in Form einer unendlichen Dreieckswelle erzeugen wollte, aber einige Werte überschreiten wollte. Ich habe am Ende einen Generator verwendet (und die Range-Funktion, wie sie auch schon verwendet wurde):
def tri_wave(min, max, step=1):
while True:
yield from range(min, max, step)
yield from range(max, min, -1 * step)
Mit sorgfältig ausgewählten Werten für min, max und step (d. H. Gleichmäßig teilbar),
for value in tri_wave(0, 8, 2):
print(value, end=", ")
Ich bekomme den min und max Wert nur einmal, was mein Ziel war:
...0, 2, 4, 6, 8, 6, 4, 2, 0, 2, 4, 6, 8, 6, 4...
Ich habe damals Python 3.6 verwendet.
Ich wurde neugierig, ob es möglich ist, einen solchen Dreieckoszillator ohne Bedingungen und Aufzählungen zu implementieren. Nun, eine Möglichkeit ist folgende:
def oscillator(magnitude):
i = 0
x = y = -1
double_magnitude = magnitude + magnitude
while True:
yield i
x = (x + 1) * (1 - (x // (double_magnitude - 1))) # instead of (x + 1) % double_magnitude
y = (y + 1) * (1 - (y // (magnitude - 1))) # instead of (y + 1) % magnitude
difference = x - y # difference ∈ {0, magnitude}
derivative = (-1 * (difference > 0) + 1 * (difference == 0))
i += derivative
Die Idee dahinter ist, zwei Sägezahnwellen mit unterschiedlichen Perioden zu nehmen und voneinander abzuziehen. Das Ergebnis ist eine Rechteckwelle mit Werten in {0, Magnitude}. Dann ersetzen wir einfach {0, magnitude} durch {-1, +1}, um abgeleitete Werte für unser Zielsignal zu erhalten.
Schauen wir uns das Beispiel mit magnitude = 5
an:
o = oscillator(5)
[next(o) for _ in range(21)]
Dies gibt [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
aus.
Wenn abs()
zulässig ist, kann dies der Einfachheit halber verwendet werden. Der folgende Code gibt beispielsweise die gleiche Ausgabe wie oben aus:
[abs(5 - ((x + 5) % 10)) for x in range(21)]