On 08/31/2015 12:09 AM, Jaime Fernández del Río wrote:
There are three ways of fixing this that I see:
1. Arbitrarily choose a value to set the return to. This is equivalent to choosing a default return for `cmp` for comparisons. This preserves behavior, but feels wrong. 2. Similarly to how np.sign of a floating point array with nans returns nan for those values, return e,g, None for these cases. This is my preferred option. 3. Raise an error, along the lines of the TypeError: unorderable types that 3.x produces for some comparisons.
I think np.sign on nan object arrays should raise the error AttributeError: 'float' object has no attribute 'sign' If I've understood correctly, currently object arrays work like this: If a ufunc has an equivalent pure-python func (eg, PyNumber_Add for np.add, PyNumber_Absolute for np.abs, < for np.greater_than) then numpy calls that for objects. Otherwise, if the object defines a method with the same name as the ufunc, numpy calls that method. For example, arccos is a ufunc that has no pure python equivalent, so you get the following behavior >>> a = np.array([-1], dtype='O') >>> np.abs(a) array([1], dtype=object) >>> np.arccos(a) AttributeError: 'int' object has no attribute 'arccos' >>> class MyClass: ... def arccos(self): ... return 1 >>> b = np.array([MyClass()], dtype='O') >>> np.arccos(b) array([1], dtype=object) Now, most comparison operators (eg, greater_than) are treated a little specially in loops.c. For some reason, sign is treated just like the other comparison operators, even through technically there is no pure-python equivalent to sign. I think that because there is no pure-python 'sign', numpy should attempt to call obj.sign, and in most cases this should fail with the error above. See also http://stackoverflow.com/questions/1986152/why-doesnt-python-have-a-sign-fun... I think the fix for sign is that the 'sign' ufunc in generate_umath.py should look more like the arccos one, and we should get rid of OBJECT_sign in loops.c. I'm not 100% sure about this since I haven't followed all of how generate_umath.py works yet. ------- By the way, based on some comments I saw somewhere (apologies, I forget who by!) I wrote up a vision for how ufuncs could work for objects, here: https://gist.github.com/ahaldane/c3f9bcf1f62d898be7c7 I'm a little unsure the ideas there are a good idea since they might be made obsolete by the big dtype subclassing improvements being discussed in the numpy roadmap thread. Allan