异常
运行到无法按原计划继续时抛出的信号;可以被接住并改走另一条路,而不是假装计算仍然有效。
它是什么
异常 是程序运行到某一步无法按原计划继续时发出的信号。除数为零、名字尚未定义、文件打不开,解释器都会停下来,并报告发生了什么、在哪一行。异常不等于「写程序失败」。它是一种诚实的通知:这一步的前提不成立。
可以用 try / except 接住它,改走另一条路,而不是让整个程序崩溃。接住只是避免崩溃;该用什么值代替、是否应当停止后续计算,必须由人决定——这也是 对话式编程 里人必须验收的边界,而不是可以交给「能运行」的草稿自行含糊过去的部分。
try:
print(10 / n)
except ZeroDivisionError:
print("除数为 0,这次计算没有定义")名字从哪来
exception 的本义是「例外情况」。早期语言遇到错误往往直接停机。后来人们把「不寻常、但可以描述的事件」做成可以抛出、可以捕获的 对象,并且按 类 组织:ZeroDivisionError、ValueError、TypeError 各管一类问题。try 是「尝试执行」,except 是「若发生某种例外」。
运行时异常与语法错误不是同一件事。缺引号、缩进 对不齐,属于程序还未能开始跑就会被拒绝的结构问题。
它怎么工作
解释器执行到非法运算时,创建一个异常对象并沿调用链向上寻找有没有匹配的 except。没人接,程序结束,输出区出现 traceback——从调用栈往回看的一串行号。有人接住,就执行对应的处理语句,然后继续往后走。
不是所有问题都该用异常「压下去」。公式写错了,应该改公式;输入可能为零,才值得接 ZeroDivisionError,或先用 选择 把零挡在门外。能预见到的边界,用 if 写明白往往比等它炸开再接更清晰;异常适合那些「不寻常但必须诚实面对」的事件。
生活里在哪里
实验做到某步发现试剂用完,应当停下并记录,而不是假装结果仍然有效。自动售货机货空时提示售罄,而不是继续扣钱。导航遇到封路,抛出「此路不通」,再改走备选路线。这些场景的共同点是:失败被当作一种可描述的状态,而不是被擦掉的尴尬。阅读报错时,先看最后一行的类型和那句话,再看它指出的行号——那是定位工具,不是对作者的品评。
和相近概念的差别
异常发生在运行时。语法错误发生在程序尚未按语义执行之前。
选择 是预先写好的岔路;异常是计划外的岔路。能用 if 说清楚的边界(例如除数是否为零),优先写在选择里。print 报错信息给人看;raise 则是主动抛出,让上层决定怎么处理。空的 except: 把所有错误吞掉,等于关掉仪器上的警报灯。
常见误会
误会 1:报错说明作者很差。
报错是证据。先读类型与行号,再决定改公式、补边界,还是接住某一种具体的异常。
误会 2:用一个空的 except: 把所有错误吞掉,程序就「更健壮」。
问题被藏起来,后面更难查。要接,就接具体的类型,并写明代替方案。
误会 3:接住异常之后,原来的错误计算仍然可用。
接住只是避免崩溃。该用什么值代替、是否结束本次计算,必须写出来。能运行,不等于那一次运算有意义。
想知道更多
- 书:埃里克·马瑟斯《Python编程:从入门到实践(第3版)》
- 书:艾伦·唐尼《像计算机科学家一样思考Python(第2版)》
- 书:布鲁克希尔《计算机科学概论》
未登录时不会保存学习进度