提问人:grigoryvp 提问时间:4/13/2009 最后编辑:martineaugrigoryvp 更新时间:9/27/2023 访问量:1730660
如何模拟 do-while 循环?
How to emulate a do-while loop?
问:
我需要在 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"
它不是“1,2,3,done”,而是打印以下输出:
[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', ' File "test_python.py", line 8, in <module>
s = i.next()
', 'StopIteration
']
我能做些什么来捕获“停止迭代”异常并中断一段时间 正确循环?
为什么可能需要这样的东西的一个例子在下面显示为伪代码。
状态机:
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
答:
你为什么不直接做
for s in l :
print s
print "done"
?
评论
我不确定你想做什么。您可以实现如下所示的 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
评论
异常会破坏循环,所以你不妨在循环外处理它。
try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
我猜你的代码的问题是没有定义内部的行为。通常只上升一级,例如 inside 直接进入(如果存在)out of the ,但不是 out of the loop。break
except
break
break
try
finally
try
相关 PEP:http://www.python.org/dev/peps/pep-3136
相关问题:打破嵌套循环
评论
看看这是否有帮助:
在异常处理程序中设置一个标志,并在处理 s 之前检查它。
flagBreak = false;
while True :
if flagBreak : break
if s :
print s
try :
s = i.next()
except StopIteration :
flagBreak = true
print "done"
评论
while not flagBreak:
if (flagBreak) : break
flag
done
endOfIteration
while not done: ...
do {
stuff()
} while (condition())
->
while True:
stuff()
if not condition():
break
你可以做一个函数:
def do_while(stuff, condition):
while condition(stuff()):
pass
但 1)它很丑。 2)条件应该是一个带有一个参数的函数,应该由东西填充(这是不使用经典while循环的唯一原因。
评论
while True: stuff(); if not condition(): break
这里有一个更疯狂的解决方案,它采用了不同的模式——使用协程。代码仍然非常相似,但有一个重要的区别;根本没有退出条件!协程(实际上是协程链)只是在您停止向它提供数据时停止。
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)
上面的代码将所有令牌收集为元组,我假设原始代码中 和 之间没有区别。tokens
.append()
.add()
评论
下面是模拟 do-while 循环的一种非常简单的方法:
condition = True
while condition:
# loop body here
condition = test_loop_condition()
# end of loop
do-while 循环的主要特征是循环体始终至少执行一次,并且条件在循环体的底部进行计算。此处显示的控制结构可以同时实现这两项任务,而无需异常或中断语句。它确实引入了一个额外的布尔变量。
评论
break
test_loop_condition()
if condition:
condition
more
notDone
break
has_no_errors
end_reached
while not end_reached
while condition is True:
stuff()
else:
stuff()
评论
stuff
while condition:
is True
condition
stuff()
对于包含 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()
或者,当不需要“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
评论
try
快速破解:
def dowhile(func = None, condition = None):
if not func or not condition:
return
else:
func()
while condition():
func()
像这样使用:
>>> x = 10
>>> def f():
... global x
... x = x - 1
>>> def c():
global x
return x > 0
>>> dowhile(f, c)
>>> print x
0
我下面的代码可能是一个有用的实现,突出了我所理解的 do-while 与 while.
因此,在这种情况下,您总是至少经历一次循环。
first_pass = True
while first_pass or condition:
first_pass = False
do_stuff()
评论
while condition or first_pass:
condition
first_pass
condition
如果你所处的场景中,你在资源不可用时循环,或者类似的东西引发异常,你可以使用类似的东西
import time
while True:
try:
f = open('some/path', 'r')
except IOError:
print('File could not be read. Retrying in 5 seconds')
time.sleep(5)
else:
break
我这样做的方式如下......
condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
在我看来,这似乎是一个简单的解决方案,我很惊讶我还没有在这里看到它。这显然也可以反转为
while not condition:
等。
评论
对我来说,一个典型的 while 循环是这样的:
xBool = True
# A counter to force a condition (eg. yCount = some integer value)
while xBool:
# set up the condition (eg. if yCount > 0):
(Do something)
yCount = yCount - 1
else:
# (condition is not met, set xBool False)
xBool = False
我可以包括一个 for..如果情况需要,也可以在 while 循环中循环,用于循环另一组条件。
内置的 iter 函数专门用于:
for x in iter(YOUR_FN, TERM_VAL):
...
例如(在 Py2 和 Py3 中测试):
class Easy:
X = 0
@classmethod
def com(cls):
cls.X += 1
return cls.X
for x in iter(Easy.com, 10):
print(">>>", x)
如果要给出终止条件而不是值,则始终可以设置相等,并要求该相等为 。True
Python 3.8 给出了答案。
它被称为赋值表达式。从文档中:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
评论
do
while
functools.partial()
iter()
for block in iter(partial, file.read, 256), ""): process(block)
do = True; while do: ; something(); if (do := condition()): complain();
你想知道:
我该怎么做才能捕获“停止迭代”异常并正确中断 while 循环?
您可以如下所示,并且还利用了 Python 3.8 中引入的赋值表达式功能(又名“海象运算符”):
list_of_ints = [1, 2, 3]
iterator = iter(list_of_ints)
try:
while (element := next(iterator)):
print(element)
except StopIteration:
print("done")
另一种可能性(从 Python 2.6 到 3.x 都可以使用)是为内置的 next()
函数提供默认
参数以避免异常:StopIteration
SENTINEL = object() # Unique object.
list_of_ints = [1, 2, 3]
iterator = iter(list_of_ints)
while True:
element = next(iterator, SENTINEL)
if element is SENTINEL:
break
print(element)
print("done")
我相信 python 上的这种 do-while 模拟具有最接近 C 和 Java 中存在的 do-while 结构格式的语法格式。
do = True
while do:
[...]
do = <condition>
评论
do = <condition>
do = <condition>
do ... while
do ... while
While 循环:
while condition:
print("hello")
Do while 循环:
while True:
print("hello")
if not condition:
break
此外,您可以使用任何真正的布尔值作为条件:
while 1:
print("hello")
if not condition:
break
另一种变体:
check = 1
while check:
print("hello")
check = condition
while True:
try:
# stuff
stuff_1()
if some_cond:
continue
if other_cond:
break
stuff_2()
finally:
# condition
if not condition:
break
- [x] 仅在运行后选中
condition
stuff
- [x] 不是函数调用
stuff
- [x] 不是函数调用
condition
- [x] 可以包含流量控制
stuff
- [ ] 避免检查是否调用(可以使用另一个布尔值完成)
condition
stuff
break
评论
try...finally
您可以在 Python 3.8 中使用 walrus 运算符进行一些清理:
list_of_ints = [ 1, 2, None, 3 ]
iterator = iter(list_of_ints)
_sentinel = object()
while True:
if (i := next(iterator, _sentinel)) is _sentinel:
break
print(i)
这在 之外没有重复的逻辑。它还处理列表中计算结果为 的值。while
False
基于 evan54 的回答:
通过定义帮助程序类
class FirstAccess:
def __init__(self):
self._accessed = False
def __bool__(self):
if self._accessed:
return False
self._accessed = True
return True
可以将标志的更新保存在循环体中,因为它通过访问它来更新:
first_pass = FirstAccess()
while first_pass or condition:
do_stuff()
评论
s=i.next()