Как pytest.approx выполняет свою магию? - PullRequest
1 голос
/ 14 мая 2019

Функция pytest approx кажется действительно классной, и, как говорится в их документации , она использует действительно интуитивный синтаксис:

>>> from pytest import approx
>>> 0.1 + 0.2 == approx(0.3)
True
>>> 1 + 1e-8 == approx(1)
True

Но как это сделать?на самом деле работа ?В первом примере, скажем, левая сторона сводится к чему-то вроде 0.29999..., так как же я могу иметь что-то на правой стороне, которое оценивается как равное ему?Знает ли функция approx как посмотреть значение l * оператора ==?Тот факт, что approx на самом деле работает, кажется чистым колдовством, может кто-нибудь объяснить, как он выполняет свой изящный маленький трюк?

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Это стандартная привязка модели данных в пользовательский __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 голос
/ 14 мая 2019

Из исходного кода я обнаружил, что они создают соответствующие Приблизительные версии классов. Например, у них есть ApproxDecimal, ApproxScalar, ApproxMapping и так далее. Функция приблизительно проверяет тип передаваемого вами значения, а затем назначает ему соответствующий приблизительный класс, который они определили.

Итак, когда вы вводите:

0.1 + 0.2 == approx(0.3)

ок изменяет его на:

0.1 + 0.2 == ApproxDecimal(0.3)

Теперь эти классы Approx реализуют соответствующие функции __eq__() и __repr__(), которые помогают python выполнять сравнение. Следовательно, они могут определить логику приближенного сопоставления в этих Приближенных классах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...