Search code examples
pythonnumpycomparisonoperatorsboolean-expression

How does Pythons double-sided inequality work? and why doesn't it work for numpy arrays?


In Python you can do the following;

>>> 3 < 4 < 5
True
>>> 3 < 4 < 4
False

How does this work? I would have thought that 4 < 5 would return a boolean, and so 3 < True should return False, or 3 < 4 should return a boolean and so True < 4 should maybe return True if True could be cast as an integer 1?.

And why doesn't it work for numpy arrays?

>>> 1 < np.array([1, 2, 3]) < 3
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Could it be made to work for numpy arrays?


Solution

  • Per the Python docs:

    Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

    So your example is equivalent to:

    1 < np.array([1, 2, 3]) and np.array([1, 2, 3]) < 3
    

    so each subterm is expected to result in a boolean value. But the subterm:

    1 < np.array([1, 2, 3])
    

    results in a new numpy array containing:

    [False, True, True]
    

    It is this value that Python is trying to interpret as a boolean value. It fails to do that, producing the error message:

    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    

    I expect that the desired expression here is:

    (1 < np.array([1, 2, 3])).all() and (np.array([1, 2, 3]) < 3).all()
    

    which can't be simplified to use comparison chaining.