在 python 迭代器类中,多次调用同一方法(如 `jacobi_iteration()`)会导致循环重复执行、状态重置,从而引发计数错误(如 `itr` 归零或返回异常值),根本原因在于方法未被缓存且每次调用都重新初始化迭代状态。
你遇到的 itr 计数异常(如从 20 突然变为 0,最终返回 1)并非 while 循环本身逻辑错误,而是方法被重复调用导致的状态冲突。观察你的调用代码:
|--------------------------------------------------------------------------------------------------------------------------|
| print``(``'(a) Jacobi solution:'``, p_15.Jacobi_iteration()[0], ``'\n iteration count:'``, p_15.Jacobi_iteration()[1]) |
这里 p_15.Jacobi_iteration() 被调用了两次 :第一次取解 0,第二次取迭代次数 1。由于 Jacobi_iteration() 是一个有状态的纯计算方法(内部维护 itr = \[\]、更新 curr_sol/next_sol、依赖收敛判断 acc_test),每次调用都会:
- 重置 itr = list(\[\]);
- 用 self.ini 重新初始化 curr_sol 和 next_sol;
- 从头开始迭代,直到首次满足收敛条件。
因此,两次独立调用可能因浮点精度、初始状态微小差异或收敛判定边界条件,导致:
- 第一次调用迭代了 N 次后收敛;
- 第二次调用因数值累积误差或 acc_test 的非幂等性(如 scarborough 中对零值的特殊处理),可能在第 1 次迭代就"意外"满足条件(尤其当 acc=1 精度较低时),从而返回 len(itr) == 1。
✅ 正确做法:始终只调用一次方法,并解包结果,避免重复执行:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| result = p_15.Jacobi_iteration() solution, iteration_count = result[0], result[1] print``(``'(a) Jacobi solution:'``, solution, ``'\n iteration count:'``, iteration_count) |
或更清晰地使用解包(推荐):
|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| solution, itr_count = p_15.Jacobi_iteration() # 单次调用,原子性获取全部结果 print``(``'(a) Jacobi solution:'``, solution) print``(``'iteration count:'``, itr_count) |
⚠️ 额外注意事项:
-
acc_test 方法存在潜在缺陷:acc_test *= self.scarborough(...) 使用乘法累积布尔值,但 False * True == 0,而 bool(0) == False,这虽能工作,但语义不直观;建议改用 all():复制AI写代码
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|def acc_test(self, ini_vec, next_vec):``checks = []``fori in range(ini_vec.shape[0]):``checks.append(self.scarborough(ini_vec[i,0], next_vec[i,0], self.acc + math.log10(2)))``returnall(checks) # 清晰、安全、符合直觉| -
nthsol_update 中 n-1 索引易引发 IndexError(当 i=0 时访问 n-1=-1);应统一使用 i 而非 n-1(方法参数名为 n,但循环传入的是 i,实际应为 i):复制AI写代码
|------------------------------------------------------------------------------------------------------------------------------------------|
|# 错误(原代码)work_mat = np.``delete``(work_mat, n-1, axis=1)[n-1, :]# 正确(使用 i)work_mat = np.``delete``(work_mat, i, axis=1)[i, :]|
while 循环计数失效的根本原因往往不在循环语法,而在方法调用方式破坏了状态一致性。在涉及迭代、状态更新或数值收敛的类方法中,务必遵循「一次调用、完整获取」原则,并通过解包或命名元组提升可读性与健壮性。