在Python中模拟do-while循环?

gri*_*yvp 731 python while-loop do-while

我需要在Python程序中模拟do-while循环.不幸的是,以下简单的代码不起作用:

list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None

while True:
  if element:
    print element

  try:
    element = iterator.next()
  except StopIteration:
    break

print "done"
Run Code Online (Sandbox Code Playgroud)

而不是"1,2,3,完成",它打印以下输出:

[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', '  File "test_python.py", line 8, in <module>
    s = i.next()
', 'StopIteration
']
Run Code Online (Sandbox Code Playgroud)

我能做些什么来捕获'stop iteration'异常并正确地打破while循环?

以下将伪代码示为可能需要这样的事物的示例.

状态机:

s = ""
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] )
    else
      state = STATE_CODE
      # Re-evaluate same line
      continue
  try :
    s = i.next()
  except StopIteration :
    break
Run Code Online (Sandbox Code Playgroud)

Tom*_*Tom 905

我不确定你要做什么.您可以像这样实现do-while循环:

while True:
  stuff()
  if fail_condition:
    break
Run Code Online (Sandbox Code Playgroud)

要么:

stuff()
while not fail_condition:
  stuff()
Run Code Online (Sandbox Code Playgroud)

您正在尝试使用do while循环来打印列表中的内容?为什么不使用:

for i in l:
  print i
print "done"
Run Code Online (Sandbox Code Playgroud)

更新:

你有一个行列表吗?你想继续迭代吗?怎么样:

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

这看起来像你想要的东西吗?使用您的代码示例,它将是:

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
Run Code Online (Sandbox Code Playgroud)

  • 另请参阅[PEP 315](https://www.python.org/dev/peps/pep-0315/)了解官方立场/理由:"建议使用该语言的用户使用内部的真实形式if-break当do-while循环是合适的." (33认同)
  • 令人遗憾的是python没有do-while循环.Python干了,嗯? (3认同)
  • 我需要创建一个状态机。在状态机中,重新评估 CURRENT 语句是正常情况,因此我需要“继续”而不迭代下一项。我不知道如何在“for s in l:”迭代中做这样的事情:(。在 do-while 循环中,“continue”将重新评估当前项目,迭代结束 (2认同)

小智 290

这是一个模拟do-while循环的非常简单的方法:

condition = True
while condition:
    # loop body here
    condition = test_loop_condition()
# end of loop
Run Code Online (Sandbox Code Playgroud)

do-while循环的关键特性是循环体总是至少执行一次,并且在循环体的底部评估条件.这里显示的控制结构完成了这两个,不需要异常或break语句.它确实引入了一个额外的布尔变量.

  • 我最喜欢这个解决方案的原因是它没有添加另一个条件,它仍然只是一个循环,如果你为辅助变量选择一个好名字,整个结构就很清楚了. (13认同)
  • 它并不总是添加额外的布尔变量.通常存在已经存在的状态可以被测试的东西. (11认同)
  • @ToolmakerSteve我不同意.我很少在循环中使用`break`,当我在代码中遇到它时,我发现循环通常可以在没有它的情况下编写.提出的解决方案是,IMO,*在python中表示do while构造的最清晰的方法. (6认同)
  • 注意:虽然这确实解决了原始问题,但这种方法不如使用"break"灵活.具体来说,如果在`test_loop_condition()`之后需要逻辑,那么一旦完成就不应该执行它,它必须包含在`if condition:`中.顺便说一下,"条件"是模糊的.更具描述性:`more`或`notDone`. (4认同)

eva*_*n54 72

我下面的代码可能是一个有用的实施,强调的主要区别 VS 据我所知.

所以在这种情况下,你总是至少经历一次循环.

first_pass = True
while first_pass or condition:
    first_pass = False
    do_stuff()
Run Code Online (Sandbox Code Playgroud)

  • @markhahn 这真的很小,但如果你关心这些细节,你可以在循环中插入 2 个布尔值:`while 条件或 first_pass:`。然后 `condition` 总是首先被评估,而整体的 `first_pass` 只被评估两次(第一次和最后一次迭代)。不要忘记在循环之前将“条件”初始化为您想要的任何内容。 (6认同)
  • 我认为,正确的答案是正确的.另外,它可以避免**break**,以便在try/except块中安全使用. (2认同)
  • @AkhilNambiar 这没有问题吗?这不是第一次……在第一次通过之后。 (2认同)

var*_*tec 33

异常将打破循环,因此您可以在循环外处理它.

try:
  while True:
    if s:
      print s
    s = i.next()
except StopIteration:   
  pass
Run Code Online (Sandbox Code Playgroud)

我猜你的代码的问题是没有定义break内部行为except.通常break只有一个级别,所以例如break内部try直接进入finally(如果存在)一个try,但不是循环.

相关PEP:http
://www.python.org/dev/peps/pep-3136相关问题:突破嵌套循环

  • 虽然只在try语句中包含您希望抛出异常的内容,但这样做是很好的做法,以免捕获不必要的异常. (8认同)
  • @PiPeep:RTFM,搜索EAFP. (7认同)
  • 在try/except/finally语句的任何子句中,break和continue都是完美定义的.他们只是忽略它们,然后根据需要突破或继续进行包含while或for循环的下一次迭代.作为循环结构的组件,它们仅与while和for语句相关,如果它们在到达最内层循环之前遇到类或def语句,则会触发语法错误.他们忽略if,with和try语句. (5认同)
  • @PiPeep:没问题,请记住,某些语言的真实情况可能不适用于其他语言.Python针对异常的密集使用进行了优化. (2认同)
  • ..这是一个重要的案例 (2认同)

小智 30

do {
  stuff()
} while (condition())
Run Code Online (Sandbox Code Playgroud)

- >

while True:
  stuff()
  if not condition():
    break
Run Code Online (Sandbox Code Playgroud)

你可以做一个功能:

def do_while(stuff, condition):
  while condition(stuff()):
    pass
Run Code Online (Sandbox Code Playgroud)

但是1)这很难看.2)条件应该是一个带有一个参数的函数,应该由stuff填充(这是使用经典while循环的唯一原因.)

  • 写`while True:stuff(); 如果不是条件():break`是一个非常好的主意.谢谢! (5认同)
  • @ZeD,为什么是1)丑陋?很好,恕我直言 (2认同)

Dan*_*ano 18

我相信 python 上的 do-while 模拟的语法格式最接近 C 和 Java 中的 do-while 结构格式。

do = True
while do:
    [...]
    do = <condition>
Run Code Online (Sandbox Code Playgroud)

  • 因为“do ... while”循环始终无条件地运行第一次迭代,并且仅在下一次迭代之前评估条件。 (2认同)

u0b*_*6ae 16

这是一个不同模式的疯狂解决方案 - 使用协同程序.代码仍然非常相似,但有一个重要区别; 根本没有退出条件!当您停止向数据提供数据时,协程(协程链确实)就会停止.

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)
Run Code Online (Sandbox Code Playgroud)

上面的代码将所有标记收集为元组,tokens并假设原始代码之间.append()和之间没有区别.add().

  • 你今天如何在Python 3.x中写这个? (4认同)

小智 12

我这样做的方式如下......

condition = True
while condition:
     do_stuff()
     condition = (<something that evaluates to True or False>)
Run Code Online (Sandbox Code Playgroud)

在我看来这是一个简单的解决方案,我很惊讶我已经没有在这里看到它.这显然也可以反过来

while not condition:
Run Code Online (Sandbox Code Playgroud)

等等

  • 你说“我很惊讶我还没有在这里看到它” - 但我没有看到任何区别,比方说,2010 年的 Powderflask 解决方案。它是完全相同的。(“条件 = True while 条件: # 此处循环体 条件 = test_loop_condition() # 循环结束”) (3认同)

Mar*_*ark 10

对于包含try语句的do-while循环

loop = True
while loop:
    generic_stuff()
    try:
        questionable_stuff()
#       to break from successful completion
#       loop = False  
    except:
        optional_stuff()
#       to break from unsuccessful completion - 
#       the case referenced in the OP's question
        loop = False
   finally:
        more_generic_stuff()
Run Code Online (Sandbox Code Playgroud)

或者,当不需要'finally'条款时

while True:
    generic_stuff()
    try:
        questionable_stuff()
#       to break from successful completion
#       break  
    except:
        optional_stuff()
#       to break from unsuccessful completion - 
#       the case referenced in the OP's question
        break
Run Code Online (Sandbox Code Playgroud)


小智 9

Python 3.8 给出了答案。

它被称为赋值表达式。从文档

# Loop over fixed length blocks
while (block := f.read(256)) != '':
    process(block)
Run Code Online (Sandbox Code Playgroud)

  • 没有。`do` _body_ `while` _condition_ 首先执行_body_,然后评估_condition_。你的构造首先检查条件。有一段时间...做循环。 (6认同)

neh*_*iah 8

while 循环:

while condition:
  print("hello")
  
Run Code Online (Sandbox Code Playgroud)

执行 while 循环:

while True:
  print("hello")
  if not condition:
    break
Run Code Online (Sandbox Code Playgroud)

您也可以使用任何 true 布尔值作为条件:

while 1:
  print("hello")
  if not condition:
    break
Run Code Online (Sandbox Code Playgroud)

另一种变体:

check = 1
while check:
    print("hello")
    check = condition
Run Code Online (Sandbox Code Playgroud)


MuS*_*eng 7

while condition is True: 
  stuff()
else:
  stuff()
Run Code Online (Sandbox Code Playgroud)

  • 所有需要的是`while condition:`因为`是True`是隐含的. (10认同)
  • EW.这似乎比使用休息时更加丑陋. (8认同)
  • 这很聪明,但它需要`stuff`作为函数或代码体重复. (5认同)
  • 不一样的逻辑,因为在条件的最后一次迭代!= True:它最后一次调用代码.作为***Do While***,首先调用代码,然后在重新运行之前检查条件.Do While:**执行块一次; 然后检查并重新运行**,这个答案:**检查并重新运行; 然后执行一次代码块**.很大的区别! (4认同)
  • 如果 `condition` 依赖于 `stuff()` 的某个内部变量,则此操作失败,因为该变量当时未定义。 (2认同)

Naf*_*Kay 7

快速破解:

def dowhile(func = None, condition = None):
    if not func or not condition:
        return
    else:
        func()
        while condition():
            func()
Run Code Online (Sandbox Code Playgroud)

使用如下:

>>> x = 10
>>> def f():
...     global x
...     x = x - 1
>>> def c():
        global x
        return x > 0
>>> dowhile(f, c)
>>> print x
0
Run Code Online (Sandbox Code Playgroud)