在原地更改子类的`ndarray`视图

Peq*_*que 15 python numpy

假设我有一个简单的Test类继承自numpy.ndarray(子类化的文档ndarray).该类创建一个对象,该对象是另一个对象的局部视图ndarray.现在我想创建一个就地修改这个视图的方法.就像是:

import numpy


class Test(numpy.ndarray):

    def __new__(cls, info='Test class'):
        base = numpy.ndarray.__new__(cls, (6, 2), dtype=float)
        view = base[0:2, :]
        view.info = info
        return view

    def __array_finalize__(self, obj):
        if obj is None:
            return
        self.info = getattr(obj, 'info', None)

    def change_view(self, start, stop):
        """This is the method I'd like to implement"""
        # Incorrect, but represents what I am looking for
        self = self.base[start:stop]


if __name__ == '__main__':
    t = Test()
    print(t)
    print(t.info)
    t.change_view(1, 5)
    print(t)
    print(t.info)
Run Code Online (Sandbox Code Playgroud)

我希望该方法.change_view(x)修改.base属性的视图以显示行[1:5]而不是[0:2]默认情况下的行__new__().

这可能吗?如果是这样,怎么样?否则,为什么不呢?请注意,.base永远不会更改(它总是占用相同的内存空间),我只想更改它的视图.

笔记

  • 请参阅中的评论change_view().我知道这self = self.base[start:stop]是不正确的,我知道并理解为什么,但我认为这是一个代表我正在寻找的东西的简短方法.
  • 如下面的答案所述,人们可以想到self[:] = ...self.data = ....但是,在更改视图大小时这将不起作用(情况确实如此).

参考

这里已经提出了这个问题(或者至少它是一个类似的情况),但是答案提到了返回修改后的数组的解决方案(即没有就地修改)或者使用了包装器对象(即具有数组的属性)待修改).

我知道这些可能性,我知道它们可以更简单甚至更方便.但是,我想了解为什么(如果是这样的话)不可能做我想要的.

Nat*_*ith 2

1)您无法就地更改 ndarray 实例或子类实例指向的数据。对不起!事实证明,可以就地更改 ndarray 实例指向的数据,但这是一个糟糕的主意,希望很快就会被删除:-)。请参阅https://github.com/numpy/numpy/issues/7093

2)你尝试这样分配self只会改变self方法本地绑定内变量的绑定,我担心这表明对Python的执行和对象模型如何工作存在相当基本的误解。我之所以提出这个问题,是因为成功的子类化ndarray困难真的很难。几乎不可能。pandas(例如,流行库的开发人员放弃了。)尽管该文档给出了误导性的印象,但 numpy 并不是真正设计来支持子类化的,而且它的工作效果也不是很好。我通常建议没有人尝试子类化ndarray;如果你还不是一名专业的 Python 程序员,那么这个数字会增加十倍。也许我们会删除那个愚蠢的页面并完全禁用子类化,除非它会破坏向后兼容性:-(。我建议找到一种不同的策略来解决您的问题。