Skip to content

Commit c9e119c

Browse files
committed
3.4
1 parent bf52834 commit c9e119c

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

3.4.md

+51
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,54 @@ Never printed if x is 0
6969

7070
这个例子表明,`invert`中的`print`表达式永远不会求值,反之,控制流跳到了`handler`中的`except`子句组中。将`ZeroDivisionError e`强制转为字符串会得到由`handler: 'division by zero'`返回的人类可读的字符串。
7171

72+
## 3.4.1 异常对象
73+
74+
异常对象本身就带有属性,例如在`assert`语句中的错误信息,以及有关异常产生处的信息。用户定义的异常类可以携带额外的属性。
75+
76+
在第一章中,我们实现了牛顿法来寻找任何函数的零点。下面的例子定义类一个异常类,无论何时`ValueError`出现,它都返回迭代改进过程中所发现的最佳猜测值。数学错误(`ValueError`的一种)在`sqrt`在负数上调用时产生。这个异常由抛出`IterImproveError`处理,它将牛顿迭代法的最新猜测值储存为参数。
77+
78+
首先,我们定义了新的类,继承自`Exception`
79+
80+
```py
81+
>>> class IterImproveError(Exception):
82+
def __init__(self, last_guess):
83+
self.last_guess = last_guess
84+
```
85+
86+
下面,我们定义了`IterImprove`的一个版本,我们的通用迭代改进算法。这个版本通过抛出`IterImproveError`异常,储存最新的猜测值来处理任何`ValueError`。像之前一样,`iter_improve`接受两个函数作为参数,每个函数都接受单一的数值参数。`update`函数返回新的猜测值,而`done`函数返回布尔值,表明改进是否收敛到了正确的值。
87+
88+
```py
89+
>>> def iter_improve(update, done, guess=1, max_updates=1000):
90+
k = 0
91+
try:
92+
while not done(guess) and k < max_updates:
93+
guess = update(guess)
94+
k = k + 1
95+
return guess
96+
except ValueError:
97+
raise IterImproveError(guess)
98+
```
99+
100+
最后,我们定义了`find_root`,它返回`iter_improve`的结果。`iter_improve`应用于由`newton_update`返回的牛顿更函数。`newton_update`定义在第一章,在这个例子中无需任何改变。`find_root`的这个版本用过返回它的最后一个猜测之来处理`IterImproveError`
101+
102+
```py
103+
>>> def find_root(f, guess=1):
104+
def done(x):
105+
return f(x) == 0
106+
try:
107+
return iter_improve(newton_update(f), done, guess)
108+
except IterImproveError as e:
109+
return e.last_guess
110+
```
111+
112+
考虑一下使用`find_root`来寻找`2 * x ** 2 + sqrt(x)`的零点。这个函数的一个零点是`0`,但是在任何负数上求解它会产生`ValueError`。我们第一章的牛顿法实现会产生异常,并且不能返回任何零点的猜测值。我们的修订版实现在错误之前返回了最新的猜测值。
113+
114+
```py
115+
>>> from math import sqrt
116+
>>> find_root(lambda x: 2*x*x + sqrt(x))
117+
-0.030211203830201594
118+
```
119+
120+
虽然这个近似值仍旧距离正确的答案`0`很远,一些应用更倾向于这个近似而不是`ValueError`
121+
122+
异常是另一个技巧,帮助我们将程序细节划分为模块化的部分。在这个例子中,Python 的异常机制允许我们分离迭代改进的逻辑,它在`try`子句组中没有发生改变,以及错误处理的逻辑,它出现在`except`子句中。我们也会发现,异常在使用 Python 实现解释器时是个非常实用的特性。

0 commit comments

Comments
 (0)