Python:如何告诉for循环从函数继续?

时间:2011-05-20 11:08:53

标签: python continue

有时我需要在for循环中使用以下模式。有时在同一个循环中不止一次:

    try:
        var = 'attempt to do something that may fail on a number of levels'
    except Exception, e:
        log(e)
        continue

现在我没有看到在函数中包装它的好方法,因为它不能return continue

def attempt(this):
    try:
        return this
    except Exception, e:
        log(e)
        # 1. continue # <-- syntax error: continue not properly in loop or
        # 2. return continue # <-- invalid syntax
        # 3.
        return False # <-- this sort of works, but makes me feel powerless

如果我return False,我可以:

    var = attempt('to do something that may fail on a number of levels')
    if not var:
        continue

但我觉得这不是正义。我想从continue函数中将for循环告诉attempt(或伪造它)。

9 个答案:

答案 0 :(得分:9)

Python已经有了一个非常好的构造来做这件事并且不使用continue

for i in range(10):
    try:
        r = 1.0 / (i % 2)
    except Exception, e:
        print(e)
    else:
        print(r)

但是,我不会嵌套这个,或者你的代码很快会变得非常难看。

在你的情况下,我可能会做更多这样的事情,因为对单个函数和flat is better than nested进行单元测试要容易得多:

#!/usr/bin/env python

def something_that_may_raise(i):
    return 1.0 / (i % 2)

def handle(e):
    print("Exception: " + str(e))

def do_something_with(result):
    print("No exception: " + str(result))

def wrap_process(i):
    try:
        result = something_that_may_raise(i)
    except ZeroDivisionError, e:
        handle(e)
    except OverflowError, e:
        handle(e) # Realistically, this will be a different handler...
    else:
        do_something_with(result)

for i in range(10):
    wrap_process(i)

请记住始终catch specific exceptions。如果您不希望抛出特定异常,则继续处理循环可能不安全。

编辑以下评论:

如果你真的不想处理异常,我仍然认为这是个坏主意,那么抓住所有异常(except:)而不是handle(e),只需pass 。此时wrap_process()将结束,跳过完成实际工作的else: - 块,然后您将进入for循环的下一次迭代。

请记住,Errors should never pass silently

答案 1 :(得分:5)

异常的整个想法是它们跨多个间接层工作,即,如果您的调用层次结构内部有错误(或任何其他异常状态),您仍然可以捕获它在更高的层次上并妥善处理。

在你的情况下,假设你有一个函数attempt()调用函数attempt2()和attempt3()调用层次结构,并且attempt3()可能遇到一个异常状态,它应该导致主循环终止:< / p>

class JustContinueException(Exception):
    pass

for i in range(0,99):
    try:
        var = attempt() # calls attempt2() and attempt3() in turn
    except JustContinueException:
        continue # we don't need to log anything here
    except Exception, e:
        log(e)
        continue

    foo(bar)

def attempt3():
    try:
        # do something
    except Exception, e:
        # do something with e, if needed
        raise # reraise exception, so we catch it downstream

你甚至可以自己抛出一个虚拟异常,这只会导致循环终止,甚至不会被记录。

def attempt3():
    raise JustContinueException()

答案 2 :(得分:3)

也许你想继续?你可以去看看Eric Lippert explains them如何(如果你已经准备好了你的思绪,但在Python中它看起来有点像这样:

def attempt(operation, continuation):
    try:
        operation()
    except:
        log('operation failed!')
    continuation()

你可以在你的循环中做到:

attempt(attempt_something, lambda: foo(bar)) # attempt_something is a function

答案 3 :(得分:2)

认为您在foo工作的所有项目上映射attempt。所以attempt是一个过滤器,很容易将其写为生成器:

def attempted( items ):
    for item in items:
        try:
            yield attempt( item )
        except Exception, e:
            log(e)

print [foo(bar) for bar in attempted( items )]

答案 4 :(得分:1)

你可以用这个:

for l in loop:
  attempt() and foo(bar)

但你应该确保attempt()返回True或False。

但是,真的,Johnsyweb的回答可能更好。

答案 5 :(得分:1)

我通常不会发布第二个答案,但如果您真的不喜欢my first answer,这是另一种方法。

请记住,函数可以返回tuple

#!/usr/bin/env python

def something_that_mail_fail(i):
    failed = False
    result = None
    try:
        result = 1.0 / (i % 4)
    except:
        failed = True # But we don't care
    return failed, result

for i in range(20):
    failed, result = something_that_mail_fail(i)
    if failed:
        continue
    for rah in ['rah'] * 3:
        print(rah)
    print(result)

我认为try ... except ... else是要走的路,但你不应该默默地忽略错误。 警告经纪人以及所有这些。

答案 6 :(得分:1)

除了上下文,我只想简短地回答这个问题。不,函数不能continue可以调用它。这是因为它没有关于此上下文的信息。此外,它会引发一整类新的问题,比如如果调用该函数而没有周围的循环来处理continue会发生什么?

但是一个函数可以通过各种方式信号它希望调用者continue当前执行的任何循环。一种方法当然是返回值。例如,返回FalseNone来表示此信号。另一种发出信号的方式是提出一个特殊的Exception

class ContinuePlease(Exception): pass

def f():
    raise ContinuePlease()

for i in range(10):
    try:
        f()
    except ContinuePlease:
        continue

答案 7 :(得分:0)

将for循环放在try之外,除了block ... simple ...; - )

import sys
if '3.4' in sys.version:
    from termcolor import colored

def list_attributes(module_name): '''Import the module before calling this func on it.s ''' for index, method in enumerate(dir(module_name)): try: method = str(method) module = 'email' expression = module + '.' + method print('*' * len(expression), '\n') print( str(index).upper() + '. ',colored( expression.upper(), 'red'), ' ', eval( expression ).dir() , '...' , '\n'2 ) print('' * len(expression), '\n') print( eval( expression + '.doc' ), '\n'*4, 'END OF DESCRIPTION FOR: ' + expression.upper(), '\n'*4) except (AttributeError, NameError): continue else: pass finally: pass

答案 8 :(得分:-4)

编辑:删除了我说的所有愚蠢......

最后的答案是重写整个事情,所以我不需要像那样编码。