1

i have next function:

def check_smaller_zeros(v):
   return v < 0

When i create array with numpy i can write next code for element-by-element measurement:

v_1 = numpy.array([1, 2, -4, -1])
result = check_smaller_zeros(v_1)
# result: [False, False, True, True]

but when i try repeat it with tuple, set, frozenset and list/array reise next error:

TypeError: '<' not supported between instances of 'tuple' and 'int'

what exactly allows numpy array to have the capability for this behavior? This looks convenient, but is a bit non-obvious

1
  • 2
    You can find this in broadcasting Commented Feb 20, 2020 at 13:33

2 Answers 2

2

Python allows you to override operators with special "dunder" (double underscore) methods. For example, let's make a custom data structure that inherits from tuple. To make < perform item-wise comparisons, we simply need to overwrite the __lt__ method.

In [1]: class MyList(tuple):
      :     def __lt__(self, other):
      :         return tuple(v < other for v in self)
      :

In [1]:

In [2]: l = MyList([1,2,3,4,5])

In [3]: l < 3
Out[3]: (True, True, False, False, False)

A list of all such methods can be found in the Python documentation under Data Model.

Sign up to request clarification or add additional context in comments.

2 Comments

thx for your answer. To answer the question, you just had to go to the source code and find the desired method) But he need find. In kotlin language, for example in doc this moment not very obvious - kotlinlang.org/docs/reference/…. In python have a similar list of "standard arithmetic" operations that can be overriding (how you for example make with __lt__)?
Good question, I have added a link to the corresponding part of the Python docs (i.e. data model) to the answer.
-1

np.array is very different from tuple, lists, etc. If you want to generalize your function, you have to think about each case.

In [111]: def check_smaller_zeros(v):
     ...:    if type(v) is np.array:
     ...:        return v < 0
     ...:    elif type(v) in (list, tuple):
     ...:        return [x<0 for x in v]
     ...:

In [112]: check_smaller_zeros((-1,1,2,3,4,5))
Out[112]: [True, False, False, False, False, False]

In some instance, you may can simply convert the object to a np.array. But it depends form the object and you have to define the use cases in advance.

In [114]: def check_smaller_zeros(v):
     ...:    if type(v) is np.array:
     ...:        return v < 0
     ...:    else:
     ...:        return np.array(v) < 0
     ...:
     ...:

In [115]: check_smaller_zeros((-1,1,2,3,4,5))
Out[115]: array([True, False, False, False, False, False])

3 Comments

np.array is not a type - it's a function that constructs arrays. Calling the first version of your function on an array returns None, and calling the second version on an array makes an unnecessary copy before performing the comparison. Also, if you're going to return different output types for different input types, it makes more sense to return a tuple as output for tuple input than to return a list.
The second version of your code could be simplified to return np.asarray(v) < 0.
Anyway, this post doesn't answer the question, which is how NumPy arrays support their behavior. The accepted answer answers the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.