pytest approx
函数看起来非常酷,就像他们在documentation中所说的那样,它使用了非常直观的语法:
>>> from pytest import approx
>>> 0.1 + 0.2 == approx(0.3)
True
>>> 1 + 1e-8 == approx(1)
True
但这实际上是如何工作的??在第一个示例中,假设左侧减少为0.29999...
之类的东西,那么如何在右侧得到与之相等的东西呢? approx
函数是否以某种方式知道如何查看==
运算符的左值? approx
实际上有效的事实看来像是纯巫术,有人可以解释它如何完成其巧妙的小技巧吗?
答案 0 :(得分:2)
这是进入自定义__eq__
的标准数据模型挂钩。
下面的简化示例应为您阐明“法术”。
>>> class MyObj:
... def __eq__(self, other):
... print(self, "is being compared with", other)
... return "potato"
...
>>> obj = MyObj()
>>> 0.1 + 0.2 == obj
<__main__.MyObj object at 0xcafef00d> is being compared with 0.30000000000000004
'potato'
请注意,float.__eq__
将首先尝试处理此比较。上面显示的行为以及approx(0.3)
的行为都非常依赖float
已明确“退出”与MyObj
实例进行比较的事实。它通过返回一个特殊值NotImplemented
来做到这一点:
>>> (0.1+0.2).__eq__(obj)
NotImplemented
有关实际的pytest实现,请查看python_api.py::ApproxScalar
。
答案 1 :(得分:1)
从源代码中,我可以发现它们创建了相应的类的近似版本。例如,它们具有ApproxDecimal
,ApproxScalar
,ApproxMapping
等。近似函数会检查您传递的值的类型,然后为其分配一个他们定义的对应的近似类。
因此,当您输入:
0.1 + 0.2 == approx(0.3)
大约将其更改为:
0.1 + 0.2 == ApproxDecimal(0.3)
现在,这些Approx类实现了相应的__eq__()
和__repr__()
函数,可帮助python执行比较。因此,他们能够在这些近似类中定义用于近似匹配的逻辑。