简体   繁体   English

pytest.approx如何实现其魔力?

[英]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. 例如,它们具有ApproxDecimalApproxScalarApproxMapping等。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM