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"
[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
#1 楼
我不确定您要做什么。您可以实现如下所示的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
评论
我需要创建一个状态机。在状态机中,重新评估CURRENT语句是正常情况,因此我需要“继续”而不迭代下一项。我不知道如何在'for s in l:'迭代中做这样的事情:(。在do-while循环中,'continue'将重新评估当前项,最后迭代
– grigoryvp
09年4月13日在6:41
您是说需要跟踪列表中的位置吗?这样,当您返回相同状态时,您可以从上次中断的地方接机吗?给更多的背景。看来使用列表中的索引可能会更好。
–汤姆
09年4月13日在6:48
谢谢,我对您的伪代码发表了评论……您的示例似乎有点糟糕,因为无论您处于什么状态,您似乎都以相同的方式处理“ //”。此外,您正在处理注释的真实代码吗?如果您的字符串带有斜线怎么办?即:打印“等等// <-这会惹您生气吗?”
–汤姆
09年4月13日在7:44
真遗憾,python没有do-while循环。 Python是DRY,是吗?
– Kr0e
13年8月24日在8:53
另请参阅PEP 315的官方立场/理由:“建议该语言的用户在适当的do-while循环时使用while-True形式,并使用内部if中断。”
–dtk
16年8月15日在12:47
#2 楼
这是一种模拟do-while循环的非常简单的方法:condition = True
while condition:
# loop body here
condition = test_loop_condition()
# end of loop
do-while循环的主要特征是循环主体始终至少执行一次,并在循环主体的底部评估条件。此处显示的控制结构无需异常或break语句即可完成这两项任务。它确实引入了一个额外的布尔变量。
评论
它并不总是添加额外的布尔变量。通常,已经存在一些可以测试其状态的东西。
–马丁内
2012年10月2日17:32
我最喜欢此解决方案的原因是,它没有添加其他条件,它仍然只是一个循环,如果为辅助变量选择一个好名字,则整个结构非常清晰。
–罗伯托
13-10-8在21:04
注意:虽然这确实解决了原始问题,但是这种方法没有使用break灵活。具体来说,如果在AFTER test_loop_condition()之后需要逻辑,那么一旦完成就不应执行,必须将它包装在if条件中:顺便说一句,条件模糊。更具描述性:完成与否。
–ToolmakerSteve
13 Dec 15'0:30
@ToolmakerSteve我不同意。我很少使用中断循环,当我在自己维护的代码中遇到中断时,我发现循环通常可以在没有中断的情况下编写。 IMO提出的解决方案是用python表示do while构造的最清晰方法。
–不知情
15年9月24日在23:48
是。并通过重命名条件来增加更多的乐趣,以便第二行在do::D时读取
– SpeedCoder5
18年8月6日在17:38
#3 楼
我下面的代码可能是一个有用的实现,突出了我了解的do-while和while之间的主要区别。因此,在这种情况下,您总是至少循环一次。
first_pass = True
while first_pass or condition:
first_pass = False
do_stuff()
评论
正确答案,我认为。此外,它还可以避免折断,以便在try / except块中安全使用。
– Zv_oDD
16-2-26在19:41
jit / optimizer避免在第一次通过之后重新测试first_pass吗?否则,这将是一个令人烦恼的性能问题,尽管可能很小
– markhahn
18/12/12在22:17
@markhahn这确实很小,但是如果您关心这些细节,则可以在循环中插入两个布尔值:while条件或first_pass:。然后,始终先评估条件,并且仅对一次first_pass评估两次(第一次和最后一次迭代)。不要忘记在循环到任何所需的对象之前初始化条件。
– pLOPeGG
19年5月3日,12:36
HM,有趣的是,我实际上是故意选择了另一种方法,而不必初始化条件,因此对代码的更改最少。就是说我明白你的意思
–evan54
19年5月4日,0:10
这里的问题是现在在每个循环中first_pass都设置为False。
–阿希尔·南比亚(Akhil Nambiar)
12月3日,9:50
#4 楼
do {
stuff()
} while (condition())
->
while True:
stuff()
if not condition():
break
您可以执行以下功能:
def do_while(stuff, condition):
while condition(stuff()):
pass
>但是
1)很难看。
2)条件应该是一个带有一个参数的函数,应该由填充物填充(这是不使用经典while循环的唯一原因。)
评论
边写边写:stuff();如果没有condition():break是一个很好的主意。谢谢!
– Noctis Skytower
2012年9月11日20:05
@ZeD,为什么是1)丑陋?很好,恕我直言
–谢尔盖·洛塞夫(Sergey Lossev)
18年1月7日在23:24
@SergeyLossev很难理解程序的逻辑,因为如果它们之间有很多“填充”代码,那么它一开始会显示为无限循环。
– exic
19年4月29日在6:12
#5 楼
异常会中断循环,因此您最好在循环外进行处理。try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
我想您代码的问题是
break
内部的except
行为是没有定义的。通常,break
仅上升一级,例如break
内部的try
直接进入finally
(如果存在),而不是try
,但不是非循环。相关PEP:http://www.python.org/dev/peps/ pep-3136
相关问题:突破嵌套循环
评论
最好在try语句中包含您希望引发异常的内容,以免捕获不需要的异常。
– Paggas
09年11月2日在18:10
@PiPeep:RTFM,搜索EAFP。
–vartec
2010年11月4日,9:35
@PiPeep:没问题,请记住,对于某些语言来说是正确的,对于其他语言来说可能不是正确的。 Python已针对密集使用异常进行了优化。
–vartec
2010年11月10日16:30
在try / except / finally语句的任何子句中,break和continue都是定义明确的。它们只是忽略它们,而是根据需要中断或继续进行包含while或for循环的下一次迭代。作为循环结构的组成部分,它们仅与while和for语句相关,如果它们在到达最内层的循环之前遇到了class或def语句,则会触发语法错误。他们忽略if,with和try语句。
– ncoghlan
2011-2-18在6:41
..这是一个重要的例子
– StephenBoesch
19年3月21日在5:37
#6 楼
这是使用协程的不同模式的更疯狂的解决方案。代码仍然非常相似,但是有一个重要的区别。根本没有退出条件!当您停止向其提供数据时,协程(实际上是协程链)就停止了。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()
之间没有区别。评论
您今天将如何在Python 3.x中编写此代码?
– Noctis Skytower
2012年9月11日20:07在
#7 楼
我这样做的方式如下...condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
在我看来这是一个简单的解决方案,我很惊讶我还没有看到它在这里。显然,这也可以转换为
while not condition:
等。
评论
您说“令我感到惊讶的是,我还没有在这里看到它”,但是我认为与Powderflask自2010年以来的解决方案没有任何区别。这是完全一样的。 (“条件=条件时为True:#循环体在这里,条件= test_loop_condition()#循环结束”)
–cslotty
19年11月12日在9:53
#8 楼
做一个包含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
#9 楼
while condition is True:
stuff()
else:
stuff()
评论
w这似乎比使用中断要难看得多。
–mattdm
2012年1月26日14:42
那很聪明,但是它要求东西成为函数或代码主体要重复。
– Noctis Skytower
2012年9月11日于20:08
所需要的只是条件,因为隐式为True。
–马丁内
2012年10月2日在18:15
如果条件取决于stuff()的某个内部变量,则此操作将失败,因为此时尚未定义该变量。
–吗?
2014-2-25在20:23
逻辑不同,因为在条件!= True的最后一次迭代中,它在最后一次调用代码。作为“做时”的地方,首先调用代码一次,然后在重新运行之前检查条件。做时间:执行一次块;然后检查并重新运行,此答案:检查并重新运行;然后执行一次代码块。巨大差距!
– Zv_oDD
16-2-26在19:34
#10 楼
快速破解: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
#11 楼
Python 3.8给出了答案。它被称为赋值表达式。来自文档:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
#12 楼
为什么不只是for s in l :
print s
print "done"
?
评论
我需要创建一个状态机。在状态机中,重新评估CURRENT语句是正常情况,因此我需要“继续”而不迭代下一项。我不知道如何在'for s in l:'迭代中做这样的事情:(。在do-while循环中,'continue'将重新评估当前项,最后进行迭代。
– grigoryvp
09年4月13日在6:26
然后,您可以为状态机定义一些伪代码,以便我们向您提示最佳的pythonic解决方案吗?我对状态机了解不多(也许不是唯一的状态机),因此,如果您向我们介绍一些有关您的算法的信息,对我们来说,这将更容易为您提供帮助。
–马丁
09年4月13日在6:48
For循环不适用于以下情况:a = fun()而a =='zxc':sleep(10)a = fun()
–哈里
2013年9月19日在7:26
这完全错过了检查布尔条件的意义
– StephenBoesch
18年11月24日在14:16
#13 楼
看看是否有帮助:在异常处理程序中设置一个标志,并在进行处理之前检查它。
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来简化。
–马丁内
2012年10月2日,18:23
我避免使用名为flag的变量-我无法推断True值或False值的含义。而是使用done或endOfIteration。代码变成未完成时的代码:....
– IceArdor
2014年3月11日在20:03
#14 楼
如果您处于资源不可用或可能引发异常的类似循环的情况下,则可以使用诸如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
#15 楼
对我来说,典型的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
如果情况允许,我也可以在while循环中包含for..loop遍历另一组条件。
#16 楼
内置的iter函数专门用于:for x in iter(YOUR_FN, TERM_VAL):
...
(在Py2和3中进行了测试):
class Easy:
X = 0
@classmethod
def com(cls):
cls.X += 1
return cls.X
for x in iter(Easy.com, 10):
print(">>>", x)
如果要提供一个终止条件而不是值,则始终可以设置一个等式,并要求该等式为
True
。
评论
嗯,那不是适当的“做一会儿”;那只是“永远做”。 “ while True”和“ break”有什么问题?S. Lott:我很确定他的问题是关于如何在python中实现do的问题。因此,我不希望他的代码是完全正确的。另外,他非常接近待做...他正在“永远”循环的末尾检查条件,看是否应该休息。不是“永远做”。
所以...您的初始示例代码实际上对我来说没有问题,并且我没有得到追溯。这是do while循环的适当习惯用法,其中break条件是迭代器耗尽。通常,您将设置s = i.next()而不是设置None,并且可能会做一些初始工作,而不是仅仅使第一次循环无效。
@underrun不幸的是,该帖子未标记使用的是哪个版本的Python-原始代码段也适用于2.7,这可能是由于Python语言本身的更新所致。