[Numpy-discussion] numpy oddity

Johann Cohen-Tanugi johann.cohentanugi at gmail.com
Tue Aug 30 14:58:04 EDT 2011


I am not sure I follow : is the problem the coerce-sequences-to-ndarrays 
behavior, or is it the fact that it applies to division and not 
multiplication?
I thought the second situation is the more problematic.
Anyway, you seem to take it as a bug, should I file a ticket somewhere?
thanks,
johann

On 08/30/2011 08:17 PM, Robert Kern wrote:
> On Tue, Aug 30, 2011 at 09:52, Charles R Harris
> <charlesr.harris at gmail.com>  wrote:
>> On Tue, Aug 30, 2011 at 8:33 AM, Johann Cohen-Tanugi
>> <johann.cohentanugi at 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.
>



More information about the NumPy-Discussion mailing list