Python:我不能抛出异常,还有其他优雅的方法吗?
我所在的工作地方规定不能使用异常(可以捕获异常)。如果我有这样的代码
def f1()
if bad_thing_happen():
raise Exception('bad stuff')
...
return something
我可以把它改成这样
def f1()
if bad_thing_happen():
return [-1, None]
...
return [0, something]
调用f1的方式会是这样的
def f1_caller():
code, result = f1(param1)
if code < 0:
return code
actual_work1()
# call f1 again
code, result = f1(param2)
if code < 0:
return code
actual_work2()
...
在Python中有没有比这个更优雅的方法呢?
4 个回答
你需要使用返回码。其他的选择可能会涉及到可变的全局状态(就像C语言中的errno)或者传入一个可变的对象(比如列表),但在Python中你几乎总是想避免这两种情况。也许你可以尝试向他们解释一下异常如何让你写出更好的后置条件,而不是让返回值变得复杂,但在其他方面它们是等价的。
返回 None
是一种比较常见的做法,从概念上来说也很合理。如果你期待有返回值,但结果是没有,那就说明可能出现了问题。
另外一种方法是,如果你本来是想返回一个列表(或者字典等),可以返回一个空列表或字典。这样在用 if
语句检查时就很方便,因为在 Python 中,空的容器会被当作 False
。如果你打算遍历这个容器,甚至可能不需要特别检查它(这取决于你在函数失败时想怎么处理)。
当然,这些方法并不能告诉你函数失败的原因。所以你可以返回一个异常实例,比如 return ValueError("invalid index")
。这样你就可以用 isinstance()
来检查特定的异常(或者一般的异常),并打印出来以获得更好的错误信息。(或者你可以提供一个辅助函数,检查返回代码是否来自 Exception
。)你仍然可以创建自己的 Exception
子类;你只需返回它们,而不是抛出它们。
最后,我建议努力去改变这种不合理的政策,因为异常是 Python 工作的重要组成部分,开销很小,使用你函数的人都会期待它们的存在。
在Python中,异常并不是我们要避免的东西,反而它们常常是解决问题的一种简单方法。而且,异常携带了很多信息,可以帮助我们快速找到问题所在(通过堆栈跟踪)并识别问题(通过异常类型或消息)。
如果有人提出这种一刀切的政策,肯定是在想其他语言(可能是C++?)的情况,在那些语言中,抛出异常的成本更高(如果你的代码在一台20年前的电脑上运行,性能会受到影响)。
回答你的问题:另一种选择是返回一个错误代码。这意味着你把函数的结果和错误处理混在了一起,这样会引发(哈哈!)自己的问题。不过,返回None
通常是一个合理的方式来表示函数失败。