在 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 = []

        for i in range(ini_vec.shape[0]):

            checks.append(self.scarborough(ini_vec[i,0], next_vec[i,0], self.acc + math.log10(2)))

        return all(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 循环计数失效的根本原因往往不在循环语法,而在方法调用方式破坏了状态一致性。在涉及迭代、状态更新或数值收敛的类方法中,务必遵循「一次调用、完整获取」原则,并通过解包或命名元组提升可读性与健壮性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐