因为__eq__不返回bool,所以在任何类型的容器中使用numpy数组都会防止在没有特定于容器的工作的情况下进行相等性测试。
示例:>>> import numpy
>>> a = numpy.array(range(3))
>>> b = numpy.array(range(3))
>>> a == b
array([ True, True, True], dtype=bool)
>>> x = (a, 'banana')
>>> y = (b, 'banana')
>>> x == y
Traceback (most recent call last):
File "", line 1, in
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
这是一个可怕的问题。例如,不能为使用TestCase.assertEqual()的容器编写unittests,而必须编写自定义比较函数。假设我们编写了一个变通函数special_eq_for_numpy_and_tuples。现在我们可以在unittest中执行此操作:x = (array1, 'deserialized')
y = (array2, 'deserialized')
self.failUnless( special_eq_for_numpy_and_tuples(x, y) )
现在我们必须对可能用于存储numpy数组的每个容器类型执行此操作。此外,__eq__可能返回bool而不是bools数组:>>> a = numpy.array(range(3))
>>> b = numpy.array(range(5))
>>> a == b
False
现在,我们每个特定于容器的等式比较函数也必须处理这种特殊情况。
也许我们可以用一个亚类来修补这个疣?>>> class SaneEqualityArray (numpy.ndarray):
... def __eq__(self, other):
... return isinstance(other, SaneEqualityArray) and self.shape == other.shape and (numpy.ndarray.__eq__(self, other)).all()
...
>>> a = SaneEqualityArray( (2, 3) )
>>> a.fill(7)
>>> b = SaneEqualityArray( (2, 3) )
>>> b.fill(7)
>>> a == b
True
>>> x = (a, 'banana')
>>> y = (b, 'banana')
>>> x == y
True
>>> c = SaneEqualityArray( (7, 7) )
>>> c.fill(7)
>>> a == c
False
这样做似乎是对的。类还应该显式导出元素级比较,因为这通常很有用。