Vic*_* Sg 4 python python-3.x try-except
我尝试创建一个函数来尝试表达式并在出现错误时返回零。
def try_or_zero(exp):
try:
exp
return exp
except:
return 0
Run Code Online (Sandbox Code Playgroud)
这显然是行不通的。问题似乎在于 python 没有任何形式的惰性求值,因此表达式在传递给函数之前会被求值,因此它会在进入函数之前引发错误,因此它永远不会通过 try 逻辑。有谁知道这是否可以在Python中完成?干杯
问题似乎是 python 没有任何形式的惰性求值
呃……是的,确实如此,但可能不是您期望的形式。函数参数在传递给函数之前确实已被评估,所以
try_or_zero(foo.bar())
Run Code Online (Sandbox Code Playgroud)
确实会被执行为:
param = foo.bar()
try_or_zero(param)
Run Code Online (Sandbox Code Playgroud)
现在Python函数是普通对象(它们可以用作变量,作为参数传递给函数等),并且它们仅在应用调用运算符(括号,带或不带参数)时被调用,因此您可以将函数传递给try_or_zero和让我们try_or_zero调用该函数:
def try_or_zero(func):
try:
return func()
except Exception as e:
return 0
Run Code Online (Sandbox Code Playgroud)
现在你要反对 1/ 如果函数需要参数,这将不起作用;2/ 必须为此编写一个函数,这是 PITA - 并且这两种反对意见都是有效的。希望 Python 也有一个快捷方式来创建由单个(即使任意复杂)表达式组成的简单匿名函数:lambda。此外,Python 函数(包括“lambda 函数”——从技术上讲,它们是普通函数)是闭包——它们捕获定义它们的上下文——因此很容易将所有这些包装在一起:
a = 42
b = "c"
def add(x, y):
return x + y
result = try_or_zero(lambda: add(a, b))
Run Code Online (Sandbox Code Playgroud)
关于异常处理的附注:
首先不要使用裸露的 except,至少要使用 catch Exception(否则你可能会阻止一些异常 - 比如SysExit- 按预期工作)。
另外最好只捕获您在给定点期望的确切异常。在您的情况下,您可能需要传递一个要忽略的异常元组,即:
def try_or_zero(func, *exceptions):
if not exceptions:
exceptions = (Exception,)
try:
return func()
except exceptions as e:
return 0
a = 42
b = "c"
def add(x, y):
return x + y
result = try_or_zero(lambda: add(a, b), TypeError))
Run Code Online (Sandbox Code Playgroud)
这将防止您的代码掩盖意外错误。
最后:您可能还想在异常情况下添加对非零返回值的支持(并非所有表达式都应该返回 int ):
# XXX : python3 only, python2 doesn't accept
# keyword args after *args
def try_or(func, *exceptions, default=0):
if not exceptions:
exceptions = (Exception,)
try:
return func()
except exceptions as e:
return default
# adding lists is legit too,
# so here you may want an empty list as the return value
# instead
a = [1, 2, 3]
# but only to lists
b = ""
result = try_or(lambda: a + b, TypeError, default=[]))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1826 次 |
| 最近记录: |