Python编程中,函数遇到问题是抛出错误好还是约定返回值好
这其实是一个编码规范的问题,没有任何场景都适用的解决方案,就好比有了 list,但是还是需要 tuple,所以对于抛出异常好,还是返回值好,是需要具体情况看的。
在 C 语言中,通用的做法是函数返回一个 code 描述状态,例如 main 函数,一般返回 0 就是正常,其他数值就需要去查错误码。这种方式仍广泛使用于 HTTP API 等接口。而到了面向对象编程语言,异常也是一个类的实例,用于表达特定的意思,这样异常有了更丰富的表现方式,处理方式也显得更优雅。
但是异常的捕获就是万能的了吗?
并不是,现实情况是,不少人仍是“错误”的处理异常。例如从头到尾的一个 try except,并且捕获所有异常,这就是为了处理异常而处理异常,反而增加了代码量。
异常捕获其实也是需要讲究技术的,就好比会写代码,不一定会写出优雅的代码、高效的代码;会捕获异常,不一定会“优雅”地捕获异常。
对于开发团队的管理者来说,一些编码“规范”(例如何时改抛出异常,怎么捕获等)也是越早立下越好,对于后期项目的维护和转移是非常有利的。
对于开发者来说,一些编码“规范”的培养,不但是个人编码“素养”的提高,也是技术视野的提升。一段时间后反观自己过去的代码,一定会觉得怎么写的这么“丑陋”。
下面我也简单讲一下什么场景下该怎么“使用”异常。
如下情况应该尽量使用异常处理:
执行的错误情况非常多样化,单一的返回值无法表示多种情况执行的错误需要调用方区别对待方法的调用层次比较深,抛出异常能使代码更简洁且易读用于链式调用的方法,例如生成器模式中,避免调用方多余的判断
如下情况应该尽量避免使用异常处理:
不要用异常做条件判断,条件判断语句的性能一般更好方法返回值简单,且用于条件判断的,例如 if 语句中的子串查找都用 find 而不是 index
下面是异常处理的一些规范分享:
不要在最外层调用整段 try except,这非常不负责任,而且也不好 debug一般捕获的都是 Exception 异常的子类,一般情况下不用捕获底层异常系统一般都推荐定义自己的异常类(甚至是异常类树),即使内容是空的(最好有文档和__str__),便于区分尽量捕获明确的子类异常,用多 catch 捕获,最后可以捕获 Exception,不要上来就直接捕获 Exception,区分异常的类型能更好的帮助我们区别处理不要为了不抛出异常而去捕获并抛弃,如果不能处理,就抛给上层调用者要善于使用 finally 和 else,特别是数据库事务,连接等需要主动关闭或回滚的情况不需要每次捕获都打印日志,规划好日志级别,不然日志会难以阅读捕获严重异常后打印日志最好用 traceback 带上调用链信息,便于定位问题
先写这么多吧,语言等技术只是实现方式,最后还是得看我们需要解决的问题。