On Tue, Aug 30, 2011 at 09:52, Charles R Harris <charlesr.har...@gmail.com> wrote: > > On Tue, Aug 30, 2011 at 8:33 AM, Johann Cohen-Tanugi > <johann.cohentan...@gmail.com> wrote: >> >> I have numpy version 1.6.1 and I see the following behavior : >> >> In [380]: X >> Out[380]: 1.0476157527896641 >> >> In [381]: X.__class__ >> Out[381]: numpy.float64 >> >> In [382]: (2,3)*X >> Out[382]: (2, 3) >> >> In [383]: (2,3)/X >> Out[383]: array([ 1.90909691, 2.86364537]) >> >> In [384]: X=float(X) >> >> In [385]: (2,3)/X >> >> --------------------------------------------------------------------------- >> TypeError Traceback (most recent call >> last) >> /home/cohen/<ipython-input-385-cafbe080bfd5> in <module>() >> ----> 1 (2,3)/X >> >> TypeError: unsupported operand type(s) for /: 'tuple' and 'float' >> >> >> So it appears that X being a numpy float allows numpy to play some trick >> on the tuple so that division becomes possible, which regular built-in >> float does not allow arithmetics with tuples. >> But why is multiplication with "*" not following the same prescription? >> > > That's strange. > > In [16]: x = float64(2.1) > > In [17]: (2,3)*x > Out[17]: (2, 3, 2, 3) > > In [18]: (2,3)/x > Out[18]: array([ 0.95238095, 1.42857143]) > > Note that in the first case x is treated like an integer. In the second the > tuple is turned into an array. I think both of these cases should raise > exceptions.
In scalartypes.c.src: tatic PyObject * gentype_multiply(PyObject *m1, PyObject *m2) { PyObject *ret = NULL; long repeat; if (!PyArray_IsScalar(m1, Generic) && ((Py_TYPE(m1)->tp_as_number == NULL) || (Py_TYPE(m1)->tp_as_number->nb_multiply == NULL))) { /* Try to convert m2 to an int and try sequence repeat */ repeat = PyInt_AsLong(m2); if (repeat == -1 && PyErr_Occurred()) { return NULL; } ret = PySequence_Repeat(m1, (int) repeat); } else if (!PyArray_IsScalar(m2, Generic) && ((Py_TYPE(m2)->tp_as_number == NULL) || (Py_TYPE(m2)->tp_as_number->nb_multiply == NULL))) { /* Try to convert m1 to an int and try sequence repeat */ repeat = PyInt_AsLong(m1); if (repeat == -1 && PyErr_Occurred()) { return NULL; } ret = PySequence_Repeat(m2, (int) repeat); } if (ret == NULL) { PyErr_Clear(); /* no effect if not set */ ret = PyArray_Type.tp_as_number->nb_multiply(m1, m2); } return ret; } The PyInt_AsLong() calls should be changed to check for __index__ability, instead. Not sure about the other operators. Some people *may* be relying on the coerce-sequences-to-ndarray behavior with numpy scalars just like they do so with ndarrays. On the other hand, the repeat behavior with * should have thrown a monkey wrench to them if they were, so the number of people who do this is probably small. -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion