[Numpy-discussion] numpy migration

Timothy Hochberg tim.hochberg@ieee....
Wed Apr 25 12:41:19 CDT 2007


On 4/24/07, Duncan Smith <buzzard@contactbox.co.uk> wrote:
>
>
>
> Timothy Hochberg wrote:


[SNIP]


>
> >
> > You should be getting a warning here. Did one disappear in the cut and
> > paste? Or are you using a nonstandard shell that eats warnings? Or an
> old
> > version of numpy?
> >
>
> Python 2.5.1 / numpy 1.0.1 / IDLE (under Windows 2000).  No warning.


I don't use Idle, but I expect that it is just eating everything that goes
to stderr. It'd be easy enough to check with something like:

>>> import sys
>>> print>>sys.stderr, "Does this get printed?"
Does this get printed?

 If this doesn't print anything, then that explains why you aren't seeing a
warning.

> In any event if you want an error rather than a warning for zero division,
>
> > use:
> >
> >>>> 1/i
> >
> > Warning: divide by zero encountered in long_scalars
> > 0
> > SyntaxError: invalid syntax
> >
> >>>> N.seterr(divide='raise')
> >
> > {'over': 'print', 'divide': 'print', 'invalid': 'print', 'under':
> 'ignore'}
> >
> >>>> 1/i
> >
> > Traceback (most recent call last):
> >  File "<stdin>", line 1, in <module>
> > FloatingPointError: divide by zero encountered in long_scalars
> >
> > Although I'm not sure why that's a floating point error.
> >
>
> True, bug or feature?, I'm really looking for a ZeroDivisionError.


I'm guessing that setting this to raise just blindly converts all of the
warnings to FloatingPointErrors. I imagine if someone with some spare cycles
submitted a patch to be more specific it would be accepted. I don't have
time to dive into that right now though.

You can hack around this for the time being by using seterr(divide='call')
and installing an appropriate handler (see code below).

[snip]
>
> > ----------------------------------------------
> >
> >>
> >> An additional problem involves classes that have e.g. __rmul__ methods
> >> defined and are sufficiently similar to numpy arrays that my classes'
> >> __rmul__ methods are not invoked when using numpy scalars.
> >
> >
> >
> >
> > Try adding "__array_priority__ = 10" or somesuch to your classes. This
> > should tell numpy to back off and let your methods go first when doing
> > mixed
> > operations. Searching for "__array_priority__" will probably turn up
> some
> > examples.
> >
>
> Yes, it did.  But for my classes it seems to have no effect.  Below is a
> fairly minimal example.


As it turns out, you need __array_wrap__ also (or maybe just __array_wrap__,
but __array_priority__ won't hurt). Try this:

 """
>>> import numpy as N
>>> ex = MyClass(N.array([[6,7],[8,9]]), ['axis0', 'axis1'])
>>> v = ex.arr[0]
>>> v * ex
[[36, 49],
 [48, 63]]['axis0', 'axis1']
>>> i = ex.arr[0,0]
>>> ex
[[6, 7],
 [8, 9]]['axis0', 'axis1']
>>> ex * i
[[36, 42],
 [48, 54]]['axis0', 'axis1']
>>> i * ex
[[36, 42],
 [48, 54]]['axis0', 'axis1']
>>> ex // 0
Traceback (most recent call last):
  ...
ZeroDivisionError: integer division or modulo by zero
"""
from __future__ import division
import numpy


def handler(message, _):
    if message == 'divide by zero':
        raise ZeroDivisionError('integer division or modulo by zero')
    raise FloatingPointError(message)

numpy.seterrcall(handler)
numpy.seterr(divide='call')

class MyClass(object):
    __array_priority__ = 10

    def __init__(self, arr, labels):
        self.arr = arr
        self.labels = labels

    def __repr__(self):
        return numpy.array2string(self.arr, separator=', ') + repr(
self.labels)

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, key):
        return self.arr[key]

    def __setitem__(self, key, item):
        self.arr[key] = item

    def __array_wrap__(self, arr, context=None):
        return  self.__class__(arr, self.labels)

    def __mul__(self, other):
        return self.__class__(self.arr * other, self.labels)

    __rmul__ = __mul__

    def __floordiv__(self, other):
        return self.__class__(self.arr // other, self.labels)

    def __rfloordiv__(self, other):
        return self.__class__(other // self.arr, self.labels)

if __name__ == "__main__":
    import doctest, scratch
    doctest.testmod(scratch)



-- 

//=][=\\

tim.hochberg@ieee.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/numpy-discussion/attachments/20070425/fae3a94e/attachment.html 


More information about the Numpy-discussion mailing list