函数中的break和continue

24
def funcA(i):
   if i%3==0:
      print "Oh! No!",
      print i
      break

for i in range(100):
   funcA(i)
   print "Pass",
   print i

我知道上面的脚本不起作用。那么,如果我需要在循环中放置带有break或continue的函数,该怎么写呢?

4个回答

35

一个函数不能在调用它的代码中引发 break 或 continue。break/continue 必须直接出现在循环内部。你的选项是:

  1. 从 funcA 返回一个值,并使用该值来决定是否终止循环
  2. 在 funcA 中引发异常,并在调用代码(或更高层次的调用链)中捕获该异常
  3. 编写一个封装了 break 逻辑的生成器,并在其上迭代,而不是在 range 上进行迭代。

第三个选项类似于这样:

def gen(base):
    for item in base:
        if item%3 == 0:
           break
        yield i

for i in gen(range(1, 100)):
    print "Pass," i

这允许您将具有条件的中断通过将它们分组到基于“base”迭代器(在这种情况下是一个范围)的生成器中来实现。然后,您遍历此生成器而不是范围本身,并获得中断行为。


1
一个封装了中断逻辑的生成器? - ThunderEX
@ThunderEX - 类似于itertools.takewhile的东西。 - eumiro
@ThunderEX:是的,类似于takewhile。请看我的编辑答案。 - BrenBarn

3

详细说明BrenBarn的答案:break幸运的是不会传播。 break是打破当前循环,就这样。如果要传播事件,则应raise异常。虽然,引发异常来中断循环是一种非常丑陋的中断循环的方法,也是破坏代码的好方法。

KISS!最简单的方法是直接在循环中检查条件。

def my_condition(x):
  return x == 4

for i in xrange(100):
  if my_condition(i): break
  print i

如果出于某种原因你想要传播一个异常,那么你可以像这样使用它。
# exception example
for i in xrange(100):
  if i == 4: raise Exception("Die!")
  print i

正如提到的那样,这是一个非常丑陋的设计。想象一下,如果你忘记捕获这个异常,或者将它的类型从“Exception”更改为“MyBreakException”,并忘记在代码的更高部分的“try/except”中做出相应更改...
生成器示例具有其优点,它使您的代码更具functional style(我个人非常喜欢)。
# generator example
def conditional_generator(n, condition):
  for i in xrange(n):
    if condition(i):
      break
    else:
      yield i


for i in conditional_generator( 100, my_condition ):
  print i

...这类似于takewhile,eumiro提到过


1
def funcA(i):
   if i%3==0:
      print "Oh! No!",
      print i
      return True
   else:
      return False

for i in range(100):
   if funcA(i):
       break
   print "Pass",
   print i

2
你能否添加一份解释,说明这段代码如何回答这个问题? - anon

1

中断不会在函数之间传播,你需要直接将其放置在循环中的某个位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接