try语句的可选else子句的预期用途是什么?


当前回答

PEP 380中有一个很好的try-else示例。基本上,它归结为在算法的不同部分做不同的异常处理。

大概是这样的:

try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()

这允许您在异常发生的地方编写异常处理代码。

其他回答

Python try-else try语句的可选else子句的预期用途是什么?

其预期用途是,如果没有预期要处理的异常,则为运行更多代码提供上下文。

这个上下文避免意外处理您没有预料到的错误。

但是理解导致else子句运行的确切条件非常重要,因为return、continue和break可以中断到else的控制流。

总之

如果没有异常,并且没有被return、continue或break语句中断,else语句将运行。

其他答案忽略了最后一部分。

从文档中可以看出:

类型的控件流出时,执行可选的else子句 try子句结束

(粗体)。脚注写道:

*目前,控制“从末端流出”,除非在 异常或return、continue或break语句的执行。

它至少需要一个except子句(参见语法)。所以它实际上不是“try-else”,而是“try-except-else(-finally)”,其中else(和finally)是可选的。

Python教程详细说明了预期的用法:

The try ... except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example: for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close() The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.

示例区分else和try块后面的代码

如果处理错误,else块将不会运行。例如:

def handle_error():
    try:
        raise RuntimeError('oops!')
    except RuntimeError as error:
        print('handled a RuntimeError, no big deal.')
    else:
        print('if this prints, we had no error!') # won't print!
    print('And now we have left the try block!')  # will print!

现在,

>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!

如果执行落在try的底部(如果没有异常),else块中的语句将被执行。说实话,我从来没有找到过需要。

然而,处理异常注意到:

使用else子句更好 而不是向try中添加额外的代码 因为它避免意外 捕获非异常 由被保护的代码引发 尝试…除了声明。

因此,如果你有一个方法,例如,抛出一个IOError,你想捕捉它引发的异常,但如果第一个操作成功,你还想做其他事情,而你不想从那个操作中捕获IOError,你可能会写这样的东西:

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
    # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

如果您只是在operation_that_can_throw_ioerror()后面加上另一个other_operation_that_can_throw_ioerror(), except将捕获第二次调用的错误。如果你把它放在整个try块之后,它会一直运行,直到finally之后。else可以让你确定

第二次操作只有在没有例外的情况下才会进行, 它在最后一个块之前运行,并且 它引发的任何ioerror都不会在这里被捕获

查看Python引用,当没有异常时,else似乎在try之后执行。 当控制流出try子句的末尾时,执行可选的else子句。else子句中的异常不由前面的except子句处理。

Dive into python有一个例子,如果我理解正确的话,在try块中他们尝试导入一个模块,当失败时,你会得到异常并绑定默认值,但当它工作时,你可以选择进入else块并绑定所需的内容(参见示例和解释链接)。

如果你试图在catch块中工作,它可能会抛出另一个异常——我想这就是else块派上用场的地方。

即使你现在想不出它的用途,你可以打赌它一定会有用处的。下面是一个没有想象力的例子:

其他:

a = [1,2,3]
try:
    something = a[2]
except IndexError:
    print("out of bounds")
else:
    print(something)

没有其他的:

try:
    something = a[2]
except IndexError:
    print("out of bounds")

if "something" in locals():
    print(something)

在这里,如果没有抛出错误,则定义了变量something。您可以在try块之外删除它,但如果定义了变量,则需要进行一些混乱的检测。

下面是我喜欢使用这种模式的另一个地方:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`