Цикл вперед и назад Python - PullRequest
       28

Цикл вперед и назад Python

0 голосов
/ 05 сентября 2018

Я хочу создать бесконечный цикл, который отсчитывает от 0 до 100 до 0 (и т. Д.) И останавливается только при соблюдении какого-либо критерия сходимости внутри цикла, поэтому, в основном, что-то вроде этого:

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)

Есть ли способ объединить два цикла for над j в один, чтобы у меня не было одного и того же кода внутри циклов дважды?

Ответы [ 10 ]

0 голосов
/ 12 сентября 2018

Мне стало любопытно, можно ли реализовать такой треугольный осциллятор без условий и перечислений. Ну, один из вариантов следующий:

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

Идея заключается в том, чтобы взять 2 пилообразные волны с разными периодами и вычесть одну из другой. Результатом будет прямоугольная волна со значениями в {0, величина}. Затем мы просто заменим {0, величина} на {-1, +1} соответственно, чтобы получить производные значения для нашего целевого сигнала.

Давайте рассмотрим пример с magnitude = 5:

o = oscillator(5)
[next(o) for _ in range(21)]

Это выводит [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0].

Если разрешено abs(), его можно использовать для простоты. Например, следующий код выдает тот же вывод, что и выше:

[abs(5 - ((x + 5) % 10)) for x in range(21)]
0 голосов
/ 06 сентября 2018

Это скорее частичный ответ, чем прямой ответ на ваш вопрос, но вы также можете использовать понятие тригонометрических функций и их колебаний для имитации цикла «назад и вперед».

Если у нас есть функция cos с амплитудой 100, смещенная влево и вверх, так что f(x) = 0 и 0 <= f(x) <= 100, тогда мы получим формулу f(x) = 50(cos(x-pi)+1) (график графика можно найти здесь . Диапазон - это то, что вам нужно, и колебание происходит, поэтому нет необходимости отменять какие-либо значения.

>>> 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

Конечно, проблема заключается в том, что функция не дает целочисленных значений так легко, поэтому это не так полезно - но это может быть полезно для будущих читателей, где тригонометрические функции могут быть полезны для их случая.

0 голосов
/ 09 сентября 2018

Недавно у меня была похожая проблема, когда я также хотел создать значения в форме бесконечной треугольной волны, но хотел перешагнуть через некоторые значения. Я закончил тем, что использовал генератор (и функция диапазона, как и другие, также использовал):

def tri_wave(min, max, step=1):
    while True:
        yield from range(min, max, step)
        yield from range(max, min, -1 * step)

С тщательно отобранными значениями min, max и step (то есть делится равномерно),

for value in tri_wave(0, 8, 2):
    print(value, end=", ")

Я получаю минимальное и максимальное значение только один раз, что и было моей целью:

...0, 2, 4, 6, 8, 6, 4, 2, 0, 2, 4, 6, 8, 6, 4...

В то время я использовал Python 3.6.

0 голосов
/ 05 сентября 2018

Вот еще одна возможность:

while notConverged:
    for i in xrange(-100, 101):
        print 100 - abs(i)
0 голосов
/ 06 сентября 2018
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

Это определяет генератор, который будет продолжать давать значения столько, сколько вам нужно. Например:

>>> 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
0 голосов
/ 05 сентября 2018
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
0 голосов
/ 05 сентября 2018

Если у вас есть повторный набор кода, используйте функцию для экономии места и усилий:

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)

Вы можете даже использовать while True

0 голосов
/ 05 сентября 2018

Как и другие ответы, вы можете использовать немного математики:

while(True):
    for i in range(200):
        if i > 100:
            i = 200 - i
0 голосов
/ 05 сентября 2018

Используйте метод chain 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)

Как предлагает @Chepner, вы можете использовать itertools.cycle() для бесконечного цикла:

from itertools import cycle, chain

for i in cycle(chain(range(0, 100, 1), range(100, 0, -1))):
    ....
0 голосов
/ 05 сентября 2018

Если вы используете Python 3.5+, вы можете использовать обычную распаковку:

for j in (*range(0, 100, 1), *range(100, 0, -1)):

или до Python 3.5, вы можете использовать itertools.chain:

from itertools import chain

...

for j in chain(range(0, 100, 1), range(100, 0, -1)):
...