异常与错误处理
引入| English | 释义 | 拼音 |
|---|---|---|
| exception/ekˈsepʃn/ | 异常 | yì cháng |
| status value | 状态值 | zhuàng tài zhí |
The loan that quietly shrank
- A renewal function returns $-1$ when a loan would pass its limit. One caller forgets to check and adds $-1$ to the loan, so a 20-day loan becomes 19 days.
- No error, no message: the failure spread silently. Exceptions exist so that a failure cannot be ignored.
Raise, catch, clean up
- Exceptions 异常 carry an error up to the code that can decide what to do.
raisethrows one;try/exceptcatches it by type. finallyruns on every path, whether the body succeeded or failed.
A small, precise hierarchy
- A custom hierarchy lets callers catch exactly what they can handle: a broad base and specific children. A handler for a parent also catches every child.
class LoanError(Exception): ...
class RenewalError(LoanError): ...
class LimitError(RenewalError): ...
except RenewalError 能接住抛出的 LimitError,因为——
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
处理器按类型沿层级匹配:父级 except 接得住每个子类。
except LimitError catches a RenewalError that was raised directly.
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
A handler catches its own type and its children. RenewalError is the parent of LimitError, so it passes by.
Check first, raise loudly
renew(Loan(20), 15)checks before changing anything and raisesLimitError('20+15 exceeds 30').- The loan still reads 20. Because a failed call changed nothing, no rollback is needed.
loan = Loan(20). The caller runs renew(loan, 15) inside a try block and catches the LimitError. What does loan.days read afterwards?
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
renew checks before changing anything, so the failed call leaves 20.
Unwinding the stack
- A raise leaves the current function and climbs frame by frame, from
renewthroughissueup tomain, running eachfinallyon the way, until anexceptmatches by type. - If nothing matches, the program stops with a traceback: loud, not silent.

Cleanup that always happens
- On the failing path
finallyruns after the handler; on the success path it runs straight after the body. - So cleanup that must happen, such as releasing a lock or closing a file, goes in
finallyor awithblock, never after the last statement.
finally 块运行于——
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
finally 是清理保证:主体之后、处理器之后、返回之前都会执行。
Status values or exceptions?
- Use a status value 状态值 (such as
Nonefor "not found") for expected outcomes the caller handles right away. - Use an exception for a broken contract or a failure the immediate caller cannot fix.
用返回值 -1 当错误码很危险,因为——
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
普通值不带任何强制力;异常无法被无视——一路展栈直到被处理。
Match each situation to the right tool.
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
Expected outcomes return values; broken contracts raise; cleanup goes in finally.
Worked example: cleanup on the failing path
locked = True,loan = Loan(28), thentry: renew(loan, 10)withexcept RenewalError: kept = 'handled'andfinally: locked = False.- $28 + 10 = 38 > 30$, so
renewraises; the handler setskept;finallyunlocks. The loan still reads 28.
In the worked example, renew raises inside the try block. Put what happens in order.
难度 3/5 · 今日首次完成可获 200 金币及少量额外奖励
The handler runs first, then finally, then normal flow resumes.
Three common slips
- A bare
except:. It even catches Ctrl-C and hides real bugs. except ...: pass. The failure vanishes and the state may be half-changed.- Catching
Exceptionwhen you meant one specific error.
Recap
- Raise on broken contracts; catch where a decision can be made; a parent handler catches its children.
- Check first, so a failed call leaves the state unchanged.
finally(orwith) runs on every path; status values are for expected, nearby outcomes.