Search code examples
pythonarraysnumpyexponentiation

Why is the inverse power of a int numpy array 0 despite "from __future__ import division"?


I always use from __future__ import division to avoid integer division problems. I just came across a case where it apparently still persists:

np.array([10])**(-1)

returns array([0]), contrary to 1/np.array([10]), which returns array([ 0.1]) as expected.

I know this can be fixed, e.g. by using np.array([10])**(-1.) or converting the array to floats using astype('float'). I would just like to know why it behaves like this, since it seems slightly inconsistent to me given that e.g. 10**(-1) gives 0.1.


Solution

  • numpy.array() uses operator overloading to implement features. ** is handled by the object.__pow__() special method, for example.

    The / operator is normally handled by object.__div__ (and the __rdiv__ method for right-hand-side values), and the from __future__ import division 'switch' causes Python to use the object.__truediv__ method instead.

    However, the ** operator is not influenced by the switch; Python will continue to call object.__pow__ and numpy won't know you used the __future__ import.

    As such, it'll continue to return integer results when you give it integer operands; it will not coerce to float even then.

    Note that Python offers a floor division operator too, in the form of the // operator and the __floordiv__ hook. There is no such flooring equivalent for exponentiation, so numpy has no other options to offer you a distinction between using float and int operands.