Python:将try-except用作表达式?

37 投票
8 回答
26485 浏览
提问于 2025-04-16 23:45

我发现自己总是遇到这样的情况:

variable = ""
try:
    variable = ... do some file loading stuff ...
except:
    variable = ""

有没有办法把这个简化成一个表达式?就像用if-else语句,你可以把:

variable = ""
if something:
    variable = somethingelse
else:
    variable = ""

变成

variable = somethingelse if something else ""

有没有类似的方式可以用在try-catch上呢?

8 个回答

16

这里有一个上下文管理器,它提供了一个小小的快捷方式:

from contextlib import contextmanager

@contextmanager
def catch(*exceptions, **kwargs):
    try:
        yield kwargs.get("default", None)
    except exceptions or Exception:
        pass

使用方法:

with catch(ZeroDivisionError, default=0) as x:
    x = 3 / 0              # error

print x                    # prints 0, the default

这个上下文管理器的基本思路是,它会返回你传入的默认值,然后这个值会被赋给你在with语句的as部分指定的变量。在这个上下文中,你可以执行一个尝试给同一个变量赋值的语句。如果这个赋值过程中出现了错误,它会被上下文管理器捕获并悄悄忽略,但因为赋值没有成功,所以默认值依然保留。

这个方法特别适合那些虽然需要多行计算,但最终结果却只有一个值的情况。

20
def try_except(success, failure):
    try:
        return success()
    except:
        return failure()

variable = try_except(do_some_file_loading_stuff, lambda: '')

我觉得这段代码自己就能说明问题。它会返回success的值,除非出现错误,这时它会返回failure的值。如果do_some_file_loading_stuff是一个表达式,而不仅仅是一个函数调用,那就把它放在lambda里。

编辑:@kindall和我稍微改进了一下他的版本,现在和我的一样快,如果你想的话调用方式完全相同,还有更多功能,而且行数也一样。快去用吧!

def try_except(success, failure, *exceptions):
    try:
        return success()
    except exceptions or Exception:
        return failure() if callable(failure) else failure
29

因为agf已经提供了我推荐的方法,这里是他的方法版本,做了一些小改进:

def try_except(success, failure, *exceptions):
    try:
        return success()
    except exceptions or Exception:
        return failure() if callable(failure) else failure

这个版本:

  1. 让你可以指定具体要捕获哪些异常,作为额外的可选参数。你应该尽量只捕获最少的异常,这样可以处理问题,而那些你无法处理的异常就让它们向上传递给调用者。

  2. 支持使用普通值和函数作为失败值。这可以让你在很多情况下不必使用lambda表达式。(当然,你可以直接用str代替lambda: ''。)

撰写回答