【发布时间】:2012-12-24 04:40:21
【问题描述】:
我使用 Python 的 unittest 模块,想检查两个复杂的数据结构是否相等。对象可以是具有各种值的字典列表:数字、字符串、Python 容器(列表/元组/字典)和numpy 数组。后者是问这个问题的原因,因为我不能这样做
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; - 比较数组(例如like this)。
似乎有点问题的是跟踪两个结构的“对应”节点,但也许zip 就是我所需要的。
问题是:有没有比这种方法更好(更简单)的替代方法?也许numpy 提供了一些工具?如果没有建议替代方案,我将实施这个想法(除非我有更好的想法)并发布作为答案。
附:我有一种模糊的感觉,我可能已经看到了解决这个问题的问题,但我现在找不到。
附言另一种方法是遍历结构并将所有numpy.arrays 转换为列表的函数,但这更容易实现吗?在我看来是一样的。
编辑:子类化numpy.ndarray 听起来很有希望,但显然我没有将比较的双方都硬编码到测试中。不过,其中一个确实是硬编码的,所以我可以:
- 使用
numpy.array的自定义子类填充它; - 在jterrace's answer 中将
isinstance(other, SaneEqualityArray)更改为isinstance(other, np.ndarray); - 在比较中始终将其用作 LHS。
我在这方面的问题是:
- 它会起作用吗(我的意思是,这听起来不错,但可能无法正确处理一些棘手的边缘情况)?在递归相等检查中,我的自定义对象是否总是以 LHS 结尾,正如我所料?
- 再说一次,有没有更好的方法(假设我得到了至少一个具有真实
numpy数组的结构)。
编辑 2:我试过了,(看似)有效的实现在 this answer 中显示。
【问题讨论】:
-
我想编写一个适用于任意数据结构的相等测试会非常困难。这些真的没有固定的结构吗?
-
@goncalopp 其中有几个,相当复杂,理论上可能会发生变化。我不想依赖它,特别是因为我不知道有什么方法可以比较两个结构中的除了
X之外的所有内容,即使我知道X在哪里。 -
然后,就个人而言,我会采用递归函数方法。不过,我会先明确检查对象的
type- 进行盲目比较,因为第一步可能是合理的,但如果您的数据结构很大,则将是浪费,因为如果@ 987654343@ 被提出。 -
@goncalopp 感谢您的意见。性能不是关键问题,这仅用于测试目的。我更关心的是尽量减少实施和维护解决方案所需的工作量。
标签: python unit-testing numpy