Python 定义 IFERROR 函数

Python Define IFERROR function

提问人:Kalev Maricq 提问时间:7/3/2019 更新时间:7/3/2019 访问量:11589

问:

我正在尝试像在 Excel 中一样在 python 中定义我自己的 IFERROR 函数。(是的,我知道我可以写 try/except。我只是想为我经常使用的 try/except 模式创建一个内联速记。当前的用例正在尝试获取某些远程表的多个属性。用于连接到它们的模块会给出各种错误,如果发生这种情况,我只想记录在尝试获取该属性时遇到错误。

我尝试过: 搜索发现了许多线程,其中最有用的是:

在 Python 中经常重复 try/except

Python:try-except 作为表达式?

阅读这些线程后,我尝试编写以下内容:

>>> def iferror(success, failure, *exceptions):
...     try:
...         return success
...     except exceptions or Exception:
...         return failure
...
>>> iferror(1/0,0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

我还尝试使用上下文管理器(对我来说是新的):

>>> from contextlib import contextmanager as cm
>>> @cm
... def iferror(failure, *exceptions):
...     try:
...         yield
...     except exceptions or Exception:
...         return failure
...
>>> with iferror(0,ZeroDivisionError) as x:
...     x=1/0
...
>>> print(x)
None

有没有办法定义一个函数来执行预定义的 try/except 模式,如 IFERROR?

Python 异常

评论

1赞 melpomene 7/3/2019
return success()和?iferror(lambda: 1/0, 0)
0赞 Kalev Maricq 7/3/2019
我仍然使用它得到零错误除法。如果它对你有用,你能发布有效的完整代码吗?

答:

2赞 TornaxO7 7/3/2019 #1

好吧,我找到了一种方法,但我不太确定,这是否是你要找的。
首先,如果调用函数,则会发生错误,因此函数根本无法启动!因此,我给函数的第一个参数一个字符串。
因此,该函数获取您的“测试”并使用 “控制” 它。这是我的代码:
eval()

def iferror(success: str, failure, *exceptions):
    try:
        # Test
        return eval(success)

    except exceptions or Exception:
        return failure    

iferror("1/0", "Hi there!")

我希望我能希望你。

评论

1赞 Kalev Maricq 7/3/2019
这是一个有趣的想法,使用 eval。显然,并非所有东西都可以与 eval 一起使用,但我认为这可能是我的备用计划。如果没有人能想出不同的方法,我会选择这个作为答案。
6赞 melpomene 7/3/2019 #2

问题在于,在输入函数之前,函数参数会被计算(大多数编程语言都是这种情况,一个很大的例外是Haskell)。不管是什么,先运行并抛出错误。iferror(1/0,0)iferror1/0

我们必须以某种方式延迟计算,以便它发生在函数内部,在块的上下文中。一种方法是使用一个字符串 (),然后可以求值。但应该尽可能避免,并且有一个更轻量级的替代方案:函数体在函数被调用之前不会被计算,因此我们可以将表达式包装在一个函数中并传递它:1/0tryiferror('1/0', 1)iferroreval

def iferror(success, failure, *exceptions):
    try:
        return success()
    except exceptions or Exception:
        return failure

def my_expr():
    return 1/0

print(iferror(my_expr, 42))
42

这里的关键部分是我们不直接打电话。我们将其作为函数传递给 ,然后调用 ,最终执行 。my_expriferrorsuccess()return 1/0

唯一的问题是,我们必须将函数参数 () 从正常的代码流中提取出来,并放入一个单独的函数定义中,我们必须给它一个名称(即使认为它只使用一次)。1/0

这些缺点可以通过使用 来避免,它允许我们内联定义单表达式函数:lambda

def iferror(success, failure, *exceptions):
    try:
        return success()
        #             ^^
    except exceptions or Exception:
        return failure

print(iferror(lambda: 1/0, 42))
#             ^^^^^^^
42

[现场演示]

与最初的尝试相比,只需要进行两项更改:将表达式包装在 中,这会延迟计算,并使用 in 调用 lambda,这会触发函数体的计算。lambda:()try: return success()

评论

0赞 melpomene 7/3/2019
这是一种通用技术,也适用于例如PerlJavaScript(但后者不认为是错误,只是返回)。1/0Infinity