如何模拟do-这时候循环?

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

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,完成”,它打印以下输出:

[stdout:]1[stdout:]2[stdout:]3None['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_COMMENTelse :tokens.add( TOKEN_CODE, s )if state is STATE_COMMENT :if "//" in s :tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )elsestate = STATE_CODE# Re-evaluate same linecontinuetry :s = i.next()except StopIteration :break
1693785 次浏览

你为什么不干脆

for s in l :print sprint "done"

?

我不确定你想做什么。你可以像这样实现一个do-这时候循环:

while True:stuff()if fail_condition:break

或:

stuff()while not fail_condition:stuff()

你在做什么?尝试使用do这时候循环来打印列表中的内容?为什么不直接使用:

for i in l:print iprint "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_COMMENTelse :tokens.add( TOKEN_CODE, s )if state is STATE_COMMENT:if "//" in s:tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )break # get next selse:state = STATE_CODE# re-evaluate same line# continues automatically

异常将打破循环,因此您不妨在循环之外处理它。

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

我猜你的代码的问题是breakexcept中的行为没有定义。通常break只上升一个级别,所以例如try中的break直接进入finally(如果存在),从try中出来,但不超出循环。

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

看看这是否有帮助:

在异常处理程序中设置一个标志,并在处理s之前检查它。

flagBreak = false;while True :
if flagBreak : break
if s :print stry :s = i.next()except StopIteration :flagBreak = true
print "done"
do {stuff()} while (condition())

->

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

你可以做一个函数:

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

但是(1)很丑。2)条件应该是一个只有一个参数的函数,应该由东西填充(这是没有使用经典if循环的唯一原因。)

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

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 crreturn startcr
@coroutinedef collector(storage):"""Act as "sink" and collect all sent in @storage"""while True:storage.append((yield))
@coroutinedef state_machine(sink):""" .send() new parts to be tokenized by the state machine,tokens are passed on to @sink"""s = ""state = STATE_CODEwhile True:if state is STATE_CODE :if "//" in s :sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))state = STATE_COMMENTelse :sink.send(( TOKEN_CODE, s ))if state is STATE_COMMENT :if "//" in s :sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))elsestate = STATE_CODE# re-evaluate same linecontinues = (yield)
tokens = []sm = state_machine(collector(tokens))for piece in i:sm.send(piece)

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

这里有一个非常简单的方法来模拟do-这时候循环:

condition = Truewhile condition:# loop body herecondition = test_loop_condition()# end of loop

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

while condition is True:stuff()else:stuff()

用于包含try语句的do-这时循环

loop = Truewhile loop:generic_stuff()try:questionable_stuff()#       to break from successful completion#       loop = Falseexcept:optional_stuff()#       to break from unsuccessful completion -#       the case referenced in the OP's questionloop = Falsefinally:more_generic_stuff()

或者,当不需要“最终”子句时

while True:generic_stuff()try:questionable_stuff()#       to break from successful completion#       breakexcept:optional_stuff()#       to break from unsuccessful completion -#       the case referenced in the OP's questionbreak

快速破解:

def dowhile(func = None, condition = None):if not func or not condition:returnelse:func()while condition():func()

像这样使用:

>>> x = 10>>> def f():...     global x...     x = x - 1>>> def c():global xreturn x > 0>>> dowhile(f, c)>>> print x0

我下面的代码可能是一个有用的实现,突出了我所理解的之间的主要区别。

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

first_pass = Truewhile first_pass or condition:first_pass = Falsedo_stuff()

如果你在一个场景中循环,而资源是不可用的或类似的东西抛出一个异常,你可以使用类似的东西

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 = Truewhile condition:do_stuff()condition = (<something that evaluates to True or False>)

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

while not condition:

对我来说,一个典型的同时循环将是这样的:

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 - 1else:# (condition is not met, set xBool False)xBool = False

如果情况需要,我也可以在这时候循环中包含一个for…循环,用于循环另一组条件。

内置的iter函数具体执行以下操作:

for x in iter(YOUR_FN, TERM_VAL):...

例如(在Py2和Py3中测试):

class Easy:X = 0@classmethoddef com(cls):cls.X += 1return cls.X
for x in iter(Easy.com, 10):print(">>>", x)

如果你想给终止一个条件而不是一个值,你总是可以设置一个相等,并要求该相等为True

Python 3.8给出了答案。

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

# Loop over fixed length blockswhile (block := f.read(256)) != '':process(block)

你想知道:

我能做些什么来捕捉“停止迭代”异常并正确地打破一个这时循环?

您可以按如下所示执行此操作,它还使用了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)是为内置的#1函数提供#0参数以避免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:breakprint(element)
print("done")

我相信这个python上的do-同时模拟具有最接近C和Java中存在的do-同时结构格式的语法格式。

do = Truewhile do:[...]do = <condition>

而循环:

while condition:print("hello")  

执行同时循环:

while True:print("hello")if not condition:break

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

while 1:print("hello")if not condition:break

另一个变体:

check = 1while check:print("hello")check = condition
while True:try:# stuffstuff_1()if some_cond:continueif other_cond:breakstuff_2()finally:# conditionif not condition:break
  • [x]condition仅在运行stuff后检查
  • [x]stuff不是函数调用
  • [x]condition不是函数调用
  • [x]stuff可以包含流控制
  • []避免检查condition如果stuff调用break(可以用另一个布尔值完成)