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

lin*_*eak 18 python continue

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

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

现在我没有看到一个很好的方法将它包装在一个函数中,因为它不能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
Run Code Online (Sandbox Code Playgroud)

如果我return False比我能:

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

但我不认为这是正义.我想continueattempt函数内部告诉for循环(或伪造它).

Joh*_*web 10

Python已经有一个非常好的构造来做这个,它不使用continue:

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

不过,我不会嵌套,或者你的代码很快会变得非常难看.

在你的情况下,我可能会做更像这样的事情,因为它更容易对单个函数进行单元测试,而flat比嵌套更好:

#!/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)
Run Code Online (Sandbox Code Playgroud)

请记住始终捕获特定的异常.如果您不期望抛出特定异常,则继续处理循环可能不安全.

编辑以下评论:

如果你真的不想处理异常,我仍然认为这是一个坏主意,然后捕获所有异常(except:)而不是handle(e)仅仅pass.此时wrap_process()将结束,跳过else:完成实际工作的-block,然后您将转到for-loop 的下一次迭代.

请记住,错误不应该默默地传递.


Boa*_*niv 5

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

def attempt3():
    raise JustContinueException()
Run Code Online (Sandbox Code Playgroud)