起因

平时能较好的处理异常。但在自定义异常时才发现,并不了解异常。对于用的api也不真明白为什么要抛出异常,而不用其它方式。
 
针对自己的疑惑,觉得有必要好好思考下
 

异常机制的产生

语言发展是从汇编到C再到C++. 在汇编和C语言中都没有异常机制。
它们用的是错误编码机制. 直到C++才出现异常机制。
 
什么导致C++中出现异常机制?要回答它,需先了解错误编码机制的存在的缺点。
* 错误信息不全
调用信息不全; 错误种类很多,返回会过于简单.
* 默认可以被忽略
默认可以不用检查返回的错误编码,很容易使程序处在不正常状态.
* 不能跨作用域传送
只能一层层的向上传送,每层都有一堆检查错误的代码,会掩盖正常处理。
 
编码机制是为解决程序错误这个需求而生。在错误发生时最重要的是:
错误内容是什么?
在哪儿出错了?
为什么出错?
编码机制存在着缺点,不能很好解决这几个需求。
 
异常机制能完善的解决了这些问题. 所以后来语言中都加入了异常机制。
 
异常机制也就了两个重要特点:
* 沿着调用堆栈向上传递错误
* 不可忽略
前者可获得完整的调用信息,方便定位错误地点. 也可将错误处理代码分离出来。
后者明确拒绝不健康运行状态,是程序正确性的关键。
 

对异常的疑惑

一个简单的python异常
>>> a = {"a": 1, "b": 2}
>>> a.pop(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'c' is not defined
对于它我有很多疑问:
1. 为什么抛异常?返回特殊标记不行吗.
2. 什么是异常?为什么它会被定义为异常.
 
回答第一个问题
异常的特点是就是"不可忽略",上面的pop没有任何值适合作为标记,它只能抛异常. 如果忽略了,可能会让程序处在不健康状态。
 
回答第二个问题
异常是判断词,与它对的应是正常。
那么什么是正常?回答它也就可回答第二个问题了.
异常与正常其实隐藏着一个判断, 隐藏着一个判断标准。
 
那么谁在判断,谁在制定标准。答案是你。
你在决定什么是异常,什么时候该抛异常,抛什么类型的异常。
例子中就是python作者在背后做了思考/定义,决定它应该作为异常。
 

如何使用异常

当定义好什么是正常,知道哪些是不正常而且不可忽略时,就是使用异常的时候。为防止不健康运行状态. 而且不可忽略.
 
值得注意的是:通常是没法考虑全面的,会有漏掉的情况,应以保守的方法处理,对未考虑到的情况全部作为异常处理,再分辨,逐步完善。
 
异常的重要性
它是软件好坏的重要标志,任何在这上面处理不好的软件,无不是充满了坑。