Эмулировать цикл выполнения в Python?

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

Ваш слушатель, вероятно, также может проверить, что что-то выбрано, и предпринять соответствующие действия, если нет. Лучше, чем получить NPE.

692
задан Green Cloak Guy 6 December 2018 в 05:07
поделиться

7 ответов

Я не уверен, что вы пытаетесь сделать. Вы можете реализовать цикл do-while, например так:

while True:
  stuff()
  if fail_condition:
    break

Или:

stuff()
while not fail_condition:
  stuff()

Что вы делаете, пытаясь использовать цикл do while для печати содержимого списка? Почему бы просто не использовать:

for i in l:
  print i
print "done"

Обновление:

Итак, у вас есть список строк? И вы хотите продолжать повторять это? Как насчет:

for s in l: 
  while True: 
    stuff() 
    # use a "break" instead of s = i.next()

Кажется ли это чем-то близким к тому, что вы хотели бы? В вашем примере кода это будет:

for s in some_list:
  while True:
    if state is STATE_CODE:
      if "//" in s:
        tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
        state = STATE_COMMENT
      else :
        tokens.add( TOKEN_CODE, s )
    if state is STATE_COMMENT:
      if "//" in s:
        tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
        break # get next s
      else:
        state = STATE_CODE
        # re-evaluate same line
        # continues automatically
905
ответ дан 22 November 2019 в 21:31
поделиться

Исключение разорвет цикл, так что вы можете также обработать его вне цикла.

try:
  while True:
    if s:
      print s
    s = i.next()
except StopIteration:   
  pass

Я предполагаю, что проблема с вашим кодом заключается в том, что поведение break внутри , за исключением не определен. Обычно break поднимается только на один уровень вверх, поэтому, например, break внутри try переходит непосредственно к наконец (если он существует) из попробуйте , но не вне цикла.

Связанный PEP: http://www.python.org/dev/peps/pep-3136
Смежный вопрос: Выход из вложенных циклов

33
ответ дан 22 November 2019 в 21:31
поделиться
do {
  stuff()
} while (condition())

->

while True:
  stuff()
  if not condition():
    break

Вы можете сделать функцию:

def do_while(stuff, condition):
  while condition(stuff()):
    pass

Но 1) Это некрасиво. 2) Условие должно быть функцией с одним параметром, который должен быть заполнен материалом (это единственная причина, по которой не использует классический цикл while.)

30
ответ дан 22 November 2019 в 21:31
поделиться

Почему бы вам просто не сделать

for s in l :
    print s
print "done"

?

3
ответ дан 22 November 2019 в 21:31
поделиться

Посмотрите, поможет ли это:

Установите флаг в обработчике исключений и проверьте его перед работой с s.

flagBreak = false;
while True :

    if flagBreak : break

    if s :
        print s
    try :
        s = i.next()
    except StopIteration :
        flagBreak = true

print "done"
1
ответ дан 22 November 2019 в 21:31
поделиться

Вот еще более безумное решение другого паттерна - с использованием сопрограмм. Код по-прежнему очень похож, но с одним важным отличием; условий выхода нет вообще! Сопрограмма (на самом деле цепочка сопрограмм) просто останавливается, когда вы прекращаете снабжать ее данными.

def coroutine(func):
    """Coroutine decorator

    Coroutines must be started, advanced to their first "yield" point,
    and this decorator does this automatically.
    """
    def startcr(*ar, **kw):
        cr = func(*ar, **kw)
        cr.next()
        return cr
    return startcr

@coroutine
def collector(storage):
    """Act as "sink" and collect all sent in @storage"""
    while True:
        storage.append((yield))

@coroutine      
def state_machine(sink):
    """ .send() new parts to be tokenized by the state machine,
    tokens are passed on to @sink
    """ 
    s = ""
    state = STATE_CODE
    while True: 
        if state is STATE_CODE :
            if "//" in s :
                sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))
                state = STATE_COMMENT
            else :
                sink.send(( TOKEN_CODE, s ))
        if state is STATE_COMMENT :
            if "//" in s :
                sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))
            else
                state = STATE_CODE
                # re-evaluate same line
                continue
        s = (yield)

tokens = []
sm = state_machine(collector(tokens))
for piece in i:
    sm.send(piece)

Приведенный выше код собирает все токены в виде кортежей в токенах , и я предполагаю, что нет никакой разницы между .append () и .add () в исходном коде.

16
ответ дан 22 November 2019 в 21:31
поделиться

Вот очень простой способ эмуляции цикла do-while:

condition = True
while condition:
    # loop body here
    condition = test_loop_condition()
# end of loop

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

288
ответ дан 22 November 2019 в 21:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: