对于没有浮点数的字典,我们使用简单的a == b
,其中a
和b
是python字典。直到我们最终得到a
和b
在其中某处包含浮点数的情况下,此方法才有效。它们是嵌套的字典,所以我认为这给pytest.approx
带来了麻烦。
我们想要的东西会告诉我们这两个字典相等(或近似相等,但是只有在浮点近似的情况下才会失败):
{"foo": {"bar": 0.30000001}} == {"foo": {"bar": 0.30000002}}
pytest.approx()
几乎是我想要的 ,但是它不支持嵌套字典。有什么可以做我想要的东西吗?
答案 0 :(得分:2)
您可以定义自己的近似帮助程序,并支持嵌套字典。不幸的是,pytest
不支持使用自定义比较器对approx
进行增强,因此您必须编写自己的函数。但是,它并不太复杂:
import pytest
from _pytest.compat import Mapping
from _pytest.python_api import ApproxMapping
def my_approx(expected, rel=None, abs=None, nan_ok=False):
if isinstance(expected, Mapping):
return ApproxNestedMapping(expected, rel, abs, nan_ok)
return pytest.approx(expected, rel, abs, nan_ok)
class ApproxNestedMapping(ApproxMapping):
def _yield_comparisons(self, actual):
for k in self.expected.keys():
if isinstance(actual[k], type(self.expected)):
gen = ApproxNestedMapping(
self.expected[k], rel=self.rel, abs=self.abs, nan_ok=self.nan_ok
)._yield_comparisons(actual[k])
for el in gen:
yield el
else:
yield actual[k], self.expected[k]
def _check_type(self):
for key, value in self.expected.items():
if not isinstance(value, type(self.expected)):
super()._check_type()
现在使用my_approx
代替pytest.approx
:
def test_nested():
assert {'foo': {'bar': 0.30000001}} == my_approx({'foo': {'bar': 0.30000002}})
答案 1 :(得分:1)
您可以做的是将字典中的值分离出来,然后检查两个值之间的差的绝对值是否小于使它“足够接近”的值。我从here找到了函数,这是我解开嵌套字典的常用函数。
epislon = 5
def extract_nested_values(it):
if isinstance(it, list):
for sub_it in it:
yield from extract_nested_values(sub_it)
elif isinstance(it, dict):
for value in it.values():
yield from extract_nested_values(value)
else:
yield it
d = {"foo": {"bar": 0.30000001}}
#[0.30000001]
e = {"foo": {"bar": 0.30000002}}
#[0.30000002]
d_value = list(extract_nested_values(d))
e_value = list(extract_nested_values(e))
if set(d.keys()) == set(e.keys()) and abs(e_value[0] - d_value[0]) < epislon:
print('Close Enough')
else:
print("not the same")
输出:
Close Enough
答案 2 :(得分:0)
您是否考虑过复制字典(以免影响原始值)iterating through every val,并用round()
将每个浮点数舍入?
math.isclose()
也比较浮点数,但是我不知道有哪个比较嵌套字典中的所有浮点数。