[Numpy-discussion] numpy.complex

OC oc-spam66 at laposte.net
Mon Jul 23 15:29:25 EDT 2012


 > It's unPythonic just in the sense that it is unlike every other type
 > constructor in Python. int(x) returns an int, list(x) returns a list,
 > but np.complex64(x) sometimes returns a np.complex64, and sometimes it
 > returns a np.ndarray, depending on what 'x' is.

This "object factory" design pattern adds useful and natural functionality.

 > I can see an argument for deprecating this behaviour altogether and
 > referring people to the np.asarray(x, dtype=complex) form; that would
 > be cleaner and reduce confusion. Don't know if it's worth it, but
 > that's the only cleanup that I can see even being considered for these
 > constructors.

 From my experience in teaching, I can tell that even beginners have no 
problem with the fact that "complex128(1)" returns a scalar and that 
"complex128(r_[1])" returns an array. It seems to be pretty natural.

Also, from the duck-typing point of view, both returned values are 
complex, i.e. provide 'real' and 'imag' attributes and 'conjugate()' method.

On the contrary a real confusion is with "numpy.complex" acting 
differently than the other "numpy.complex*".

 > People do write "from numpy import *"

Yeah, that's what I do very often in interactive "ipython" sessions. 
Other than this, people are warned often enough that this shouldn't be 
used in real programs.

> and it would be very bad if that overwrote basic builtins like
> int/float/bool

True, but is it so bad? All the following is true when 'x' is a scalar:
   complex(x)  == numpy.complex_(x)
   bool(x)     == numpy.bool_(x)
   float(x)    == numpy.float_(x)
   int(x)      == numpy.int_(x)
   isinstance(numpy.complex_(x), complex)
   isinstance(numpy.int_(x), int)
   isinstance(numpy.float_(x), float)

However, it's indeed a problem that "numpy.complex_(1,1)" is not 
defined, contrary to "__builtin__.complex(1,1)" (but this looks easy to 
implement).

> it's very difficult to deprecate exports, so I guess this will probably
> never happen.

With the move to Python 3, people are used to movement :-)

I will just summarize my opinion and understanding, in case someone is 
interested:
* I find it ugly that:
- "numpy.real(A)" and "numpy.complex(A)" do not behave the same.
- "numpy.complex(A)" and "numpy.complex128(A)" do not behave the same.
* A solution could be to let "numpy.complex" be equal to
   "numpy.complex_" (and the same for "int", "float", "bool").
- This would overwrite builtins in case of "from numpy import *".
- This may not be that harmful, except for the fact that
   "numpy.complex_(1,1)" is not implemented, contrary to
   "__builtin__.complex(1,1)".



More information about the NumPy-Discussion mailing list