pytest.approx 如何实现它的魔力?

Mr.*_*rub 5 python pytest

pytestapprox函数看起来真的很酷,正如他们在文档中所说的那样,它使用了一种非常直观的语法:

>>> from pytest import approx
>>> 0.1 + 0.2 == approx(0.3)
True
Run Code Online (Sandbox Code Playgroud)
>>> 1 + 1e-8 == approx(1)
True
Run Code Online (Sandbox Code Playgroud)

但这实际上是如何工作的?在第一个例子中,假设左侧减少到类似0.29999...,那么我怎么能在右侧有一些评估为等于它的东西?该approx函数是否知道如何查看==运算符的左值?approx实际有效的事实似乎是纯粹的巫术,有人可以解释一下它是如何完成其​​巧妙的小技巧的吗?

wim*_*wim 6

这是一个标准的数据模型挂钩到自定义__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'
Run Code Online (Sandbox Code Playgroud)

请注意,float.__eq__将首次尝试处理此比较。上面显示的行为以及对于approx(0.3),关键依赖于float已明确“选择退出”与MyObj实例进行比较的事实。它通过返回一个特殊值来做到这一点NotImplemented

>>> (0.1+0.2).__eq__(obj)
NotImplemented
Run Code Online (Sandbox Code Playgroud)

对于实际的 pytest 实现,请查看python_api.py::ApproxScalar.