Okey I don't even know where to ask this or what I am exactly asking, but is basically what the title says: if the argument of numpy.min is a function, it doesn't matter if its defined by the user or not, the output is such function.
Let me put an example:
import numpy as np
def get_third_value(x):
return x[2]
xx = np.arange(10)
print(np.min(get_third_value)) # output: <function the_third at 0x7ffb58c2b240>
print(np.min(max)) # output: <built-in function max>
# you can even use them:
print(np.min(max)(xx)) # output : 9
print(np.min(get_third_value)(xx)) # output: 2
Why this happens? Is this the intended behavior? If so, why?
I have checked other numpy functions and the same happens in some of them
In my current ipython session I have a foo
function. In python functions are 'first class objects', that is, they can be passed around like other objects such as numbers and strings.
In [361]: foo
Out[361]: <function __main__.foo(a, b_list)>
In [362]: np.min(foo)
Out[362]: <function __main__.foo(a, b_list)>
np.min
, like many numpy functions, turns its non-array arguments into an array first:
In [363]: np.array(foo)
Out[363]: array(<function foo at 0x000001595F1CBF60>, dtype=object)
In this case, and possibly many more, np.min
just returns the only element of such a length 1 (0d) array.
Compare this case of a python float:
In [364]: np.min(1.23)
Out[364]: np.float64(1.23)
In [365]: np.array(1.23)
Out[365]: array(1.23)
In [366]: _.dtype
Out[366]: dtype('float64')
That float was made into an array with np.float64
dtype.
Look at what happens when we give it two functions:
In [367]: np.min([foo,foo])
TypeError: '<=' not supported between instances of 'function' and 'function'
Now it says it can't compare them. Now it's trying to do some sort of <=>
comparison between the elements of this list. As an experiment, define a custom class, with (or without) at least one of the comparison methods, and see what np.min
does.
Another exception to returning a single item:
In [368]: np.min('astring')
UFuncTypeError: ufunc 'minimum' did not contain a loop with signature matching types (dtype('<U7'), dtype('<U7')) -> None
In [369]: np.array('astring')
Out[369]: array('astring', dtype='<U7')
The string was turned into a numpy string dtype.
Functions np.min
have a catalog of signatures
, telling it what can be worked on. (I first wrote that np.min
is a ufunc
. That's not true. np.minimum
is a ufunc
. I have an idea of how to look up the signatures of ufunc
. I don't know about this type.)
If the string is first made into an object dtype array, it behaves just like your function case:
In [370]: np.min(np.array('string',object))
Out[370]: 'string'
In general when trying to understand the bahavior with non-array inputs, first look at what np.array(...)
does with that. Without digging further into the compiled code it will be hard to expain exactly what/why this is happending.
Compare what the python min
does. It expacts an iterable, like a list:
In [372]: min(foo)
TypeError: 'function' object is not iterable
In [373]: min([foo])
Out[373]: <function __main__.foo(a, b_list)>
In [374]: min([foo,foo])
TypeError: '<' not supported between instances of 'function' and 'function'