python - 为什么更改 numpy 子类的属性不会更改子类数组?
问题描述
当我对 numpy 数组进行子类化时遇到以下问题
例如:
import numpy
class Example(numpy.ndarray):
def __new__(cls, x, y):
dt = [('x', 'float'), ('y', 'float')]
buffer = numpy.array(zip(x, y),dtype=dt)
obj = super(Example, cls).__new__(cls, buffer.shape, dtype=dt,
buffer=buffer)
obj.x = numpy.array(x, dtype='float')
obj.y = numpy.array(y, dtype='float')
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.x = getattr(obj, 'x', None)
self.y = getattr(obj, 'y', None)
如果我对 obj.x 和 obj['x'] 进行操作,一个不会改变另一个。例如这些操作将显示不同的结果
x = [1,2,3,4]
y = [1,1,1,1]
obj = Example(x,y)
obj.x = obj.x / 2.
print obj.x, obj['x']
或者
obj = Example(x,y)
obj['x'] = obj['x'] / 2.
print obj.x, obj['x']
每当我对其中一个(obj.x 或 obj['x'])进行操作时,我怎样才能做到这一点,另一个也会改变?
解决方案
使用[('x', 'float'), ('y', 'float')]
as 数据类型告诉 numpy 创建一个结构化数组,其中包含名为x
and的字段y
。正如您所展示的,这些是使用方括号访问的。现在,您还obj.<name>
向您的类添加了属性(使用 访问)。但是,您已经为属性创建了新数组。要修复属性表示法,您需要让x
andy
属性通过这些名称指向数组字段,而不是单独的数组。所以改变
obj.x = numpy.array(x, dtype='float')
obj.y = numpy.array(y, dtype='float')
至
obj.x = obj['x']
obj.y = obj['y']
编辑这仅修复问题中的第二个测试用例。分配给x
ory
仍然分配一个新对象作为属性,而不是更新x
or y
。要解决这个问题,有必要修改__setattr__
类的方法(见这里)
def __setattr__(self, attr, value):
if attr in ['x', 'y']:
getattr(self, attr)[:] = attr
else:
setattr(self, attr, value)
然而,Numpy 已经有了一个数组类型,允许将字段作为属性访问。你可以像这样使用它
obj = np.array(np.r_[x, y], dtype=[('x', 'float'), ('y', 'float')])
obj = obj.view(np.recarray)
那么恭喜!您已经有效地重新实现了记录数组(好吧,np.recarray
不允许访问与属性或函数匹配的字段名称ndarray
。所以名称喜欢mean
或ndim
不在,而您的代码将允许这些)。当您花费数小时创建 numpy 已经拥有的东西时,这总是一个好(而且非常令人沮丧)的迹象。
推荐阅读
- azure-devops - 从 az ml cli 运行 id
- java - 部署为war时是否需要spring boot应用程序的“main”方法
- html - 视频无法在 chrome 中播放或自动播放,甚至静音 - 有时是,有时不是
- syntax - 匹配借来的枚举 - 为什么这种语法等效?
- sql-server - 如何使用 Visual Studio 2019 调试 CLR 数据库对象(存储过程)
- spring-integration - 如何从上传文件到 sftp 获得响应?
- javascript - 如何在 puppeteer 上拦截下载请求并读取被拦截的文件
- ios - NSAttributedString 和布局的奇怪问题
- python-3.x - 为什么在这里出现 NameError
- python - Python中有二维列表的规范名称吗?