如何解决numpy数组值和对象属性都可能指向内存中的相同位置吗?
在我正在开发的项目中,我想知道是否可以做类似的事情:
class P:
def __init__(self,x):
self.x = x
def __str__(self):
return str(self.x)
def __repr__(self):
return self.__str__()
obj_lst = [P(x=2),P(x=3),P(x=4),P(x=5)]
np_x = array([p.x for p in obj_lst])
obj_lst[0].x = 10
print(np_x)
预期结果将是
array([10,3,4,5])
还
np_x[2] = 20
print(obj_lst)
我会得到的,
[10,20,5]
因此,对象的属性和数组中的值都指向内存中的同一位置。
这样,我就可以将OOP抽象和复杂运算的速度用在numpy速度上。
解决方法
如果您在框外进行了一些思考(可能会稍微调整一下要求),则可以这样做。让我们颠倒设置过程的方式,并创建一个首先保存数据的缓冲区:
np_x = np.array([2,3,4,5])
现在,以不同的方式定义您的班级。除了记录x
的 value 之外,我们将指向它的指针记录为数组和索引(以后您可以对原始内存位置进行一些有趣的操作,但是对于现在)。您可以通过在类中将x
属性设置为property
并将其数据存储在同名的instance属性中,从而保持几乎完全相同的接口:
class P:
def __init__(self,buffer,offset):
self.__dict__['x'] = (buffer,offset)
@property
def x(self):
buf,off = self.__dict__['x']
return buf[off]
@x.setter
def x(self,value):
buf,off = self.__dict__['x']
buf[off] = value
def __str__(self):
return str(self.x)
def __repr__(self):
return self.__str__()
现在,您可以列出对象了。这是代码中唯一在类定义之外更改的部分:
obj_lst = [P(np_x,0),P(np_x,1),2),3)]
您的所有更改现在都是透明的,因为您共享一个缓冲区:
>>> obj_lst[0].x = 10
>>> np_x
array([10,5])
>>> np_x[-2] = 20
>>> obj_lst
[10,20,5]
与此相关的一件整洁的事情是,P
实际上可以与支持__getitem__
和__setitem__
的任何类型一起使用,而不管其如何编制索引。例如,您可以将其应用于dict
:
>>> d_x = {'a': 2,'b': 3,'c': 4,'d': 5}
>>> obj_lst = [P(d_x,'a'),P(d_x,'b'),'c'),'d')]
>>> obj_lst[0].x = 10
>>> d_x
{'a': 10,'c': 20,'d': 5}
>>> d_x['c'] = 20
>>> obj_lst
[10,5]
您还可以为numpy数组提供复杂的索引:
>>> np_x = np.arange(10)
>>> obj_lst = [P(np_x,slice(1,None,2)),[1,2,6,8])]
>>> obj_lst
[0,[1 3 5 7 9],[1 2 6 8]]
>>> obj_lst[-1].x = 100
>>> np_x
array([ 0,100,5,7,9])
>>> np_x[5:] = 20
>>> obj_lst
[0,[100 3 20 20 20],[100 100 20 20]]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。