[英]How does pytest.approx accomplish its magic?
The pytest approx
function seems really, cool, and as they say in their documentation it uses a really intuitive syntax: pytest
approx
函数看起来非常酷,正如他们在文档中所说的那样,它使用了一种非常直观的语法:
>>> from pytest import approx
>>> 0.1 + 0.2 == approx(0.3)
True
>>> 1 + 1e-8 == approx(1)
True
But how does this actually work ? 但这实际上是如何运作的呢? In the first example, let's say the left side reduces to something like
0.29999...
, so how can I have something on the right side that evaluates to being equal to it? 在第一个例子中,假设左侧
0.29999...
到0.29999...
,那么我怎样才能在右侧有一些评估等于它的东西呢? Does the approx
function somehow know how to look at the lvalue of the ==
operator? approx
函数是否知道如何查看==
运算符的左值? The fact that approx
actually works seems like pure sorcery, can someone explain how it accomplishes its neat little trick? approx
实际上工作的事实看起来像纯粹的巫术,有人可以解释它是如何完成其整洁的小技巧的吗?
This is a standard datamodel hook into a custom __eq__
. 这是自定义
__eq__
的标准数据模型挂钩。
The simplified example below should clarify the "sorcery" for you. 下面简化的例子应该为你澄清“巫术”。
>>> 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'
Note that float.__eq__
will get the first attempt at handling this comparison. 请注意,
float.__eq__
将首次尝试处理此比较。 The behavior shown above, and also for approx(0.3)
, crucially relies on the fact that float
has explicitly "opted out" of comparing with MyObj
instances. 上面显示的行为,以及
approx(0.3)
,主要依赖于float
明确“选择”与MyObj
实例进行比较的MyObj
。 It does this by returning a special value NotImplemented
: 它通过返回特殊值
NotImplemented
:
>>> (0.1+0.2).__eq__(obj)
NotImplemented
For the actual pytest implementation, look in python_api.py::ApproxScalar
. 对于实际的pytest实现,请查看
python_api.py::ApproxScalar
。
From the source code I could find that they create corresponding Approx version of the classes. 从源代码我可以发现他们创建了相应的大约类。 For example, they have
ApproxDecimal
, ApproxScalar
, ApproxMapping
and so on. 例如,它们具有
ApproxDecimal
, ApproxScalar
, ApproxMapping
等。 The approx function checks the type of the value you pass and then assigns it a corresponding approximate class that they have defined. approx函数检查您传递的值的类型,然后为其分配已定义的相应近似类。
So when you enter: 所以当你输入:
0.1 + 0.2 == approx(0.3)
the approx changes it to: 大约将其改为:
0.1 + 0.2 == ApproxDecimal(0.3)
Now these Approx classes implement corresponding __eq__()
and __repr__()
functions that help python perform the comparison. 现在这些
__repr__()
类实现相应的__eq__()
和__repr__()
函数,帮助python执行比较。 Hence they are able to define the logic for approximate matching within these Approximate classes. 因此,他们能够在这些近似类中定义近似匹配的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.