@@ -69,3 +69,54 @@ Never printed if x is 0
69
69
70
70
这个例子表明,` invert ` 中的` print ` 表达式永远不会求值,反之,控制流跳到了` handler ` 中的` except ` 子句组中。将` ZeroDivisionError e ` 强制转为字符串会得到由` handler: 'division by zero' ` 返回的人类可读的字符串。
71
71
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