
在 Python 类方法中重复调用同一迭代函数(如 Jacobi_iteration())会导致计数器被多次重置,从而返回错误的迭代次数;正确做法是仅调用一次并解包结果,避免副作用和状态不一致。
在 python 类方法中重复调用同一迭代函数(如 `jacobi_iteration()`)会导致计数器被多次重置,从而返回错误的迭代次数;正确做法是仅调用一次并解包结果,避免副作用和状态不一致。
你遇到的“itr 从 20 突然变回 0,最终返回 1”问题,并非循环逻辑或计数器本身有 bug,而是因在单条 print 语句中重复调用了 Jacobi_iteration() 方法两次:
print('(a) Jacobi solution:', p_15.Jacobi_iteration()[0], '\n iteration count:', p_15.Jacobi_iteration()[1])
这段代码实际执行了 两次完全独立的迭代过程:
- 第一次调用 p_15.Jacobi_iteration()[0]:初始化 curr_sol 和 next_sol,运行完整迭代直至收敛,返回解向量;
- 第二次调用 p_15.Jacobi_iteration()[1]:重新初始化对象状态(包括 curr_sol = deepcopy(self.ini)),再次从头开始迭代 —— 此时可能因初始条件、浮点精度或收敛判定的敏感性,在极少数步内(甚至第 1 步)就满足 acc_test == True,导致 len(itr) 返回 1。
⚠️ 关键点在于:Jacobi_iteration() 是有状态的计算过程,它依赖类实例的初始解 self.ini,并在每次调用时重置内部迭代变量(如 itr=[])。两次调用互不共享状态,因此第二次计数完全独立且不可预测。
✅ 正确写法:只调用一次,显式保存结果
result = p_15.Jacobi_iteration()
solution, iters = result[0], result[1] # 或直接解包
print('(a) Jacobi solution:', solution, '\n iteration count:', iters)
更推荐使用结构化解包,提升可读性与安全性:
solution, iteration_count = p_15.Jacobi_iteration() # ✅ 单次调用,一次解包
print('(a) Jacobi solution:', solution)
print('iteration count:', iteration_count)
? 额外建议:优化 acc_test 逻辑
当前 acc_test 使用乘积判断所有分量收敛(acc_test *= ...),但若任一分量未收敛,乘积可能为 0,导致布尔转换为 False —— 这本身合理。但需注意:
- scarborough 中 ini_sol != 0 判定存在风险(浮点比较应避免 != 0,建议用 abs(ini_sol) > 1e-12);
- math.log10(2) 的引入略显突兀,建议明确注释其物理意义(如“补偿舍入误差的额外精度位”);
- nthsol_update 中 n-1 索引易引发 IndexError(当 n=0 时),应统一采用 0-based 索引并校验边界。
? 总结:
Python 中任何带内部状态或副作用的方法(尤其是数值迭代、随机采样、IO 操作等)都应避免重复调用。始终遵循「一次调用,多次使用」原则,并通过变量缓存结果。这不仅是性能优化,更是保证逻辑正确性和调试可复现性的关键实践。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











