2

Following statement passes in my tests.

self.assertEqual(3.3, np.asarray([3.3]))

One type is numpy.float64 other is numpy.ndarray and my assumption was that this test will fail but it passes.

Following statement prints [ True]

print(3.3 == np.asarray([3.3]))

Debugging further shows that assertEquals ends up invoking unittest.case.TestCase#_baseAssertEqual which checks equality using ==:

if not first == second:
        standardMsg = '%s != %s' % _common_shorten_repr(first, second)
        msg = self._formatMessage(msg, standardMsg)
        raise self.failureException(msg)

Can someone explain why and how test self.assertEqual(3.3, np.asarray([3.3])) passes?

Edit: How == works in case you compare an array of one value with a variable and where is this behaviour documented?

M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103
Ume Habiba
  • 29
  • 2
  • 1
    But haven't you already determined why this `assertEqual` passes? As you say, `3.3 == np.asarray([3.3])` evaluates to `[ True]`. So the behavior appears to be: if `a == b` gives a [truthy](https://stackoverflow.com/questions/39983695/what-is-truthy-and-falsy-in-python-how-is-it-different-from-true-and-false) value, then `assertEqual(a,b)` will pass. – Kevin Jun 14 '18 at 12:50
  • you seem to have answered the question yourself, as noted by @Kevin. if you want you can additinaly [check the types](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertIsInstance) and fail tests, if there is a mismatch – Evgeny Jun 14 '18 at 12:59
  • @Kevin I guess my question should have been that how `==` works in case you compare an array of one value with a variable and where is this behaviour documented? – Ume Habiba Jun 14 '18 at 13:00
  • 1
    @Kevin but that does not explain why a float64 object of value 3.3 equals a ndarray holding a float64 of value 3.3 as the only element,does it? – shmee Jun 14 '18 at 13:00
  • 1
    Perhaps "Why does `3.3 == np.asarray([3.3])` evaluate to anything other than False?" is an interesting and worthwhile question, in which case I feel it ought to be asked independently of a question centered around assertEquals – Kevin Jun 14 '18 at 13:04
  • `[True]` is a true value, so of course the test passes. You want to print `not (3.3 == np.asarray([3.3]))` instead! – Martijn Pieters Jun 14 '18 at 13:24
  • @ shmee: perhaps it is less striking that `bool(np.array(True)) is True`? hard to expect `False` here, right? this is a step in the middle in evaluating `3.3 == np.array([3.3])` – Evgeny Jun 14 '18 at 13:29
  • @EvgenyPogrebnyak So you are saying that because `bool(3.3)` is True and `bool(ndarray(True))` is True, as a consequence `3.3 == ndarray(True)` must be True as well? If so, I disagree :). I guess either numpy's float64 or ndarray implementation do a conversion, either the scalar to ndarray or the ndarray to scalar. Otherwise one could also expect `5 == [5]` to be True, which it cleary is not. – shmee Jun 14 '18 at 13:39
  • @MartijnPieters But why is it `[True]` ? One can expect that comparing an array of float to a float will return false given that even types aren't same. – M-Wajeeh Jun 14 '18 at 13:43
  • 1
    @M-WaJeEh: because numpy arrays use *broadcasting*. The comparison doesn't apply to the array as a whole, instead you get a new array with the results of the comparison applied to each value in the array. You can then use the boolean array that gives to do further operations. – Martijn Pieters Jun 14 '18 at 13:58

2 Answers2

1

As explained in the numpy docs about ndarrays:

Arithmetic and comparison operations on ndarrays are defined as element-wise operations, and generally yield ndarray objects as results.

The == operation on ndarrays returns another ndarray, not a single boolean True or False.

This is useful for data processing, but it's different from almost every other python object, is which A == B would return a simple boolean.

M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103
Håken Lid
  • 22,318
  • 9
  • 52
  • 67
0

In Python one can add several __eq__ methods on a specific type, to make it comparable with another. Probably some kind of that is done with numpy.ndarray.

In that case when a == b is checked then it translates to a.__eq__(b). And if type for a has implemented __eq__ method comparison for b's type they can be compared with ==.

Source: https://docs.python.org/3/reference/datamodel.html#object.eq

Kzhi
  • 380
  • 1
  • 2
  • 11