我使用Python的unittest
模块,想要检查两个复杂数据结构是否相等。这些对象可以是包含各种值的字典列表:数字、字符串、Python容器(列表/元组/字典)和numpy
数组。后者是提出此问题的原因,因为我不能只做以下操作:
assert a == b
self.assertEqual(big_struct1, big_struct2)
因为它能够产生一个
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
我想我需要编写自己的相等性测试来解决这个问题,适用于任意结构。 我目前的想法是一个递归函数,它:
- 尝试将
arg1
的当前“节点”直接与arg2
的相应节点进行比较; - 如果没有引发异常,则继续(“终端”节点/叶子也在此处理);
- 如果捕获到
ValueError
,则会向更深处移动,直到找到numpy.array
; - 比较数组(例如像这样)。
看起来有点麻烦的是跟踪两个结构的“对应”节点,但也许 zip
就是我需要的全部。
问题是:是否有更好(更简单)的方法来解决这个问题? 也许 numpy
提供了一些工具来处理这个问题?如果没有其他建议,我将实现这个想法(除非我有更好的想法),并作为答案发布。
P.S. 我模糊地感觉到我可能见过一个解决这个问题的问题,但现在我找不到它了。
P.P.S. 另一种方法是遍历结构并将所有 numpy.array
转换为列表,但这是否更容易实现?对我来说似乎是一样的。
编辑:子类化 numpy.ndarray
听起来非常有前途,但显然我没有两个硬编码到测试中的比较。 不过,其中一个确实是硬编码的,所以我可以:
- 使用自定义的
numpy.array
子类填充它; - 按照jterrace的答案中的内容将
isinstance(other,SaneEqualityArray)
更改为isinstance(other,np.ndarray)
; - 始终将其用作比较中的LHS。
我的问题是:
- 它会工作吗(我的意思是,对我来说听起来很好,但也许一些棘手的边缘情况处理不正确)? 我的自定义对象是否始终作为递归相等性检查中的LHS,如我所预期的那样?
- 同样地,是否有更好的方法(假设我至少得到具有真正
numpy
数组的结构之一)?
编辑2:我试过了,(看起来)工作正常的实现显示在这个答案中。
X
的位置,我也不知道如何比较两个结构中除了X
以外的所有内容。 - Lev Levitskytype
类型——如果你的数据结构较大,进行盲目比较可能是可行的,但如果出现ValueError
错误,则会浪费时间,因为需要重新检查值。 - loopbackbee