Hi, I'm just coding a package for uncertain arrays using the accelerated numpy functionality intensively. I'm sorry, but I have to give some background information first. The package provides a class upy.undarray, which holds the nominal value and the uncertainty information. It has methods __add__(other), __radd__(other), ..., __eq__(other), __ne__(other), which accept both upy.undarrays and all other values suitable for coercion, thus also native numpy.ndarrays. But because numpy treats in the statement:
result = numpyarray * upyarray upyarray as a scalar, because it's not an numpy.ndarray, I have to overload the numpy arithmetics by own objects by using numpy.set_numeric_ops(add = ..., ..., equal = equal, not_equal = not_equal). The arguments are defined by the module (it will be clearifiied below). Because numpy.add etc. are ufuncs exhibiting attributes, I wrote a class to wrap them: class ufuncWrap: """Wraps numpy ufuncs. Behaves like the original, with the exception that __call__() will be overloaded.""" def __init__(self, ufunc, overload): """UFUNC is the ufunc to be wrapped. OVERLOAD is the name (string) of the undarray method to be used in overloading __call__().""" self.ufunc = ufunc self.overload = overload def __call__(self, a, b, *args, **kwargs): """When B is an undarray, call B.overload(a), else .ufunc(a, b).""" if isinstance(b, undarray): return getattr(b, self.overload)(a) else: return self.ufunc(a, b, *args, **kwargs) def __getattr__(self, attr): """Return getattr(.ufunc, ATTR).""" return getattr(self.ufunc, attr) I only have to wrap binary operators. Then, e.g.: class Equal(ufuncWrap): def __init__(self): ufuncWrap.__init__(self, numpy.equal, '__eq__') equal = Equal() This works as expected. But this approach fails (in first iteration) for a similar class NotEqual. I have let the module output the arguments passed to ufuncWrap.__call__(), and I found that the statement: result = (numpyarray != upyarray) with: numpyarray = numpy.asarray([1.0]) upyarray = upy.ndarray([2.0], error = [0.1]) is passed on to NotEqual.__call__() as the arguments: a = a numpy-array array([1.0]) b = a numpy-array array(shape = (), dtype = numpy.object), which is a scalar array holding the upy.ndarray instance passed to !=. I can work around the exhbited behaviour by: class NotEqual(ufuncWrap): def __init__(self): ufuncWrap.__init__(self, numpy.not_equal, '__ne__') def __call__(self, a, b, *args, **kwargs): # numpy's calling mechanism of not_equal() seems to have a bug, # such that b is always a numpy.ndarray. When b should be an undarray, # it is a numpy.ndarray(dtype = numpy.object, shape = ()) ... # Make the call also compatible with future, bug-fixed versions. if isinstance(b, numpy.ndarray): if b.ndim == 0: # Implement some conversion from scalar array to stored object. b = b.sum() return ufuncWrap.__call__(self, a, b, *args, **kwargs) What is the reason for the behaviour observed? I'm using numpy 1.4.0 with Python 2.5. Friedrich _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion