在条件表达式中使用raise语句

36

我该如何优雅地在我的函数中实现"武士道原则"要么胜利归来,要么战死沙场)?

return <value> if <bool> else raise <exception>

1
这里的Samurai是什么意思?您认为添加一些细节怎么样? - Wolf
1
武士道原则 - 要么凯旋而归,要么不归。如果一个函数履行了它的职责,就返回适当的结果对象;如果没有,则抛出异常。 - F3RD3F
2
哦,我明白了。也许加上一些链接会更好,比如武士道原则 - Wolf
5个回答

34

如果你一定想在表达式中使用raise,可以这样做:

def raiser(ex): raise ex

return <value> if <bool> else raiser(<exception>)

这个代码“尝试”返回raiser()的返回值,如果函数中没有无条件的raise语句,则返回值将为None


2
当配置一个依赖于环境变量的设置文件时,我发现这种简写三元运算符很方便。这样,我仍然可以在文件中拥有干净的字典行,但是当特定的设置项缺失时,也可以提供有用且更具体的错误消息。例如:{'f': os.environ.get('FOO') or raise_foobar(), ...} - Kevin

27

三元/内联 if 是一个表达式,而不是语句。你的尝试意味着“如果布尔值为真,返回值,否则返回raise expression的结果”-当然这是无意义的,因为raise exception本身就是一个语句而不是表达式。

没有办法内联实现这个操作,而且你也不应该这样做。请显式地完成它:

if not bool:
    raise MyException
return value

4
我认为这个问题实际上可以翻译成:“有没有一种方法可以将异常作为表达式而不是语句引发?”对此,答案是肯定的,就像@glglgl所建议的那样。 - user4396006

2

在三元运算符中提升变量的方法是使用 exec,具体操作如下:

def raising_ternary(x):
    return x if x else exec("raise Exception('its just not true')")

正如您所看到的,使用 True 调用它将执行三元表达式的第一部分,而使用 False 调用它将引发异常:

>>> def raising_ternary(x):
...     return x if x else exec("raise Exception('its just not true')")
... 
>>> raising_ternary(True)
True
>>> raising_ternary(False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in raising_ternary
  File "<string>", line 1, in <module>
Exception: its just not true
>>> 

4
虽然我认为这很有创意,但从Pythonic的角度来看,它也让我的眼睛流血...... - Dan Ciborowski - MSFT
4
哈哈,我知道这种建议带来的污名,但我忍不住至少要发布它让其他人看到:D - Kevin Kreiser
exec() 是危险的,不应该以这种方式使用。 - dataviews

2

我喜欢使用断言来强调成员必须存在,就像签订合同一样。

>>> def foo(self):
...     assert self.value, "Not Found"
...     return self.value

这样做你不会引发特定的异常,是吗? - F3RD3F
我也注意到 assert 和其他语言一样,只有在 debug 模式下才会被重现,所以如果你在运行时发现错误,它会断言吗? - F3RD3F
1
这不是很符合Python的风格,并且如果你在运行Python解释器时没有使用调试选项,assert语句会被忽略掉... P.D: -O:轻微优化生成的字节码;同时PYTHONOPTIMIZE=x - Tolo Palmer
当self.value = 0时会发生什么?如果我运行>>> assert 0,它会引发错误。我想你需要修改你的示例。 编辑后的问题 - Laurens Meeus

0

好的,你可以单独测试布尔值:

if expr: raise exception('foo')
return val

这样,您可以更早地测试expr


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接