You need to override __array_wrap__
in your ndarray subclass with a function that looks like this:
def __array_wrap__(self, obj):
if obj.shape == ():
return obj[()] # if ufunc output is scalar, return it
else:
return np.ndarray.__array_wrap__(self, obj)
__array_wrap__
is called after ufuncs to do cleanup work. In the default implementation special cases exact ndarrays (but not subclasses) to convert zero-rank arrays to scalars. At least this is true for some versions of numpy.