一些 Numpy 函数返回 ndarray 而不是我的子类

Posted

技术标签:

【中文标题】一些 Numpy 函数返回 ndarray 而不是我的子类【英文标题】:some Numpy functions return ndarray instead of my subclass 【发布时间】:2011-09-05 15:49:49 【问题描述】:

我正在继承 Numpy 的 ndarray 类,添加一些元数据和其他方法。我正在尝试按照this article 和that one 中的说明进行操作。但是,一些 Numpy(或 Scipy)函数返回基类“ndarray”而不是我的自定义子类。其他 Numpy 函数确实返回我的子类,我不知道差异的原因是什么。如何让所有 numpy/scipy 函数返回我的子类?这就是我所做的:

class Signal(np.ndarray):
    def __new__(cls, filename):
        #print "In __new__" #TEMP DEBUG
        ret = np.fromfile(filename, dtype = np.int32)
        ret = ret.view(cls) # convert to my class, i.e. Signal
        ret.parse_filename(filename)
        return ret

    def __array_finalize__(self, obj):
        #print "in __array_finalize__" #TEMP DEBUG
        if obj is None: return # shouldn't actually happen.
        # copy meta-fields from source, if it has them (otherwise put None's)
        self.filename = getattr(obj, "filename", None)
        self.folder = getattr(obj, "folder", None)
        self.label = getattr(obj, "label", None)
        self.date = getattr(obj, "date", None)
        self.time = getattr(obj, "time", None)
        #etc

以下是一些用法示例:

这些按预期工作 -

>>> s = Signal(filename)
>>> s2 = s[10:20]
>>> type (s2)
<class '__main__.Signal'>
>>> s3 = s + 17
>>> type (s3)
<class '__main__.Signal'>
>>> s4 = np.sqrt(s)
>>> type(s4)
<class '__main__.Signal'>

但是,这些呢?

>>> s5 = log10(s)
>>> type(s5)
<type 'numpy.ndarray'>
>>> s6 = np.fft.fft(s)
>>> type(s6)
<type 'numpy.ndarray'>

查看fftlog10 的代码我可以看到他们使用asarray(),它剥离子类并返回一个ndarray,解释行为。因此,我的问题不是“从技术上讲,为什么会发生这种情况”,而更多的是一个设计问题——我应该如何编写代码才能避免这种情况发生?

附言我是 Python 和 Stack Overflow 的新手,所以请原谅任何明显的错误或不当之处...

谢谢, 伙计。

【问题讨论】:

【参考方案1】:

我不确定fft,但np.log10 是ufunc。以下页面解释了如何确定 ufunc 的输出类型:http://docs.scipy.org/doc/numpy/reference/ufuncs.html#output-type-determination

如果fft 总是返回ndarray 我不会感到惊讶(我没有查看源代码,但 FFT 显然不符合 ufunc 的定义)。如果是这种情况,您始终可以编写自己的包装器并调用它。

【讨论】:

要对此进行扩展,您需要在您的子类中实现__array_wrap__ 方法。见docs.scipy.org/doc/numpy/user/…。 好的,我刚刚发现 Numpy 的 log10() 和 Scipy 的 log10() 之间存在差异... numpy 的 ufunc 表现良好,返回我的子类,如上面实现的那样(没有 __array_wrap__ by方式)。 scipy log10 虽然返回一个基类。有谁知道这背后的原因是什么?我应该使用哪个 log10...?实际数值输出有什么不同吗?其他功能呢?无论如何,重复的原因是什么......? 斯蒂芬,你能详细说明为什么我需要实现__array_wrap__,现在我注意到 numpy 函数实际上确实返回了我的子类,只有 Scipy 没有(见我上面的评论)?它对 Scipy 的功能有帮助吗?考虑到我没有实现__array_wrap__,我在上面的代码中所做的有什么问题吗? @tinkerer:我一直想知道 numpy 和 scipy 之间明显的重复。我刚刚发布了一个关于此的问题:***.com/questions/6200910/…

以上是关于一些 Numpy 函数返回 ndarray 而不是我的子类的主要内容,如果未能解决你的问题,请参考以下文章

Python机器学习(四十八)NumPy 矩阵库函数

Numpy 常用矩阵计算函数

Numpy 矩阵库(Matrix)

发送图像时预期的 str、bytes 或 os.PathLike 对象,而不是 numpy.ndarray

numpy ndarray 返回 index 问题

如何将PyTorch张量转换为Numpy ndarray