pytest中浮点数断言应避免==,因二进制精度限制导致0.1+0.2≠0.3;须用pytest.approx()(支持标量/结构、动态容差)或numpy.testing.assert_allclose()(适合NumPy数组、atol/rtol语义明确)。

pytest里直接用==比较浮点数为什么总失败
因为浮点数在计算机中是二进制近似表示,0.1 + 0.2 不等于 0.3,而是 0.30000000000000004。直接写 assert a == b 很容易因微小舍入误差报 AssertionError,这不是代码逻辑错,是浮点表示局限。
实操建议:
- 永远不要对浮点数用
==断言相等,除非你明确知道两个值来自同一计算路径且未经过任何中间转换 - 用
pytest.approx()替代,它默认容忍1e-6相对误差(或绝对误差,取决于值大小) -
pytest.approx()支持标量、列表、元组、字典甚至嵌套结构,自动递归比对
如何用pytest.approx()控制精度容差
pytest.approx() 的容差不是固定小数位,而是按数值大小动态选择相对/绝对误差策略。但你可以显式指定:
常见用法示例:
立即学习“Python免费学习笔记(深入)”;
import pytest <p>result = 0.1 + 0.2 assert result == pytest.approx(0.3) # 默认容差,够用 assert result == pytest.approx(0.3, abs=1e-10) # 强制绝对误差 ≤ 1e-10 assert result == pytest.approx(0.3, rel=1e-3) # 强制相对误差 ≤ 0.1% assert [1.01, 2.001] == pytest.approx([1.0, 2.0], abs=0.01) # 列表整体容差
注意:abs 和 rel 可同时传,满足任一即通过;若只传 rel 而待测值为 0,会退回到 abs 检查(否则除零)。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
对比numpy.testing.assert_allclose的适用场景
如果你项目已重度依赖 NumPy,numpy.testing.assert_allclose() 更适合批量数组断言,尤其带 atol/rtol 参数语义更明确:
import numpy as np <p>a = np.array([0.1, 0.2]) b = np.array([0.10000001, 0.20000001]) np.testing.assert_allclose(a, b, atol=1e-8) # 清晰区分绝对/相对容差
但它不兼容非 NumPy 对象(比如纯 Python list),也不像 pytest.approx() 那样能直接用于 assert 表达式右侧;出错时提示信息也更偏向调试而非测试报告。
选哪个?
- 单值、简单结构、纯 Python 项目 → 用
pytest.approx() - 涉及
np.ndarray、需要精细控制atol/rtol、已有大量 NumPy 测试 → 用np.testing.assert_allclose()
容易忽略的边界情况和坑
几个真实踩过的点:
-
pytest.approx(0)默认用abs=1e-12,但若你传rel=1e-3且期望值为 0,它不会报错,而是悄悄退到绝对容差——这点文档没强调,容易误以为“相对误差生效了” - 嵌套字典中某个 float 值超差,错误提示只显示顶层 key,不展开路径,排查要手动二分;建议对复杂结构先抽离关键字段再断言
- 在
parametrize中用pytest.approx()作预期值没问题,但别把它当变量名传进 fixture——approx对象不可哈希,会导致TypeError: unhashable type
浮点断言真正的难点不在语法,而在判断“这个容差是否业务可接受”。比如金融计算要求 abs=1e-2(分),科学模拟可能要 rel=1e-15;得跟领域逻辑对齐,不能全靠默认值蒙混过关。

















