猿问

是否可以让 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, 3, 20, 5]

因此,对象的属性和数组中的值都指向内存中的同一位置。


这样我就可以一方面使用 OOP 抽象,另一方面使用 numpy 的速度来进行复杂的代数运算。


九州编程
浏览 84回答 1
1回答

米琪卡哇伊

如果您跳出框框思考(并且可能稍微调整您的要求),您就可以做到这一点。让我们反转设置方式并首先创建一个保存数据的缓冲区:np_x = np.array([2, 3, 4, 5])现在稍微不同地定义你的类。我们不会记录的值x,而是将指向它的指针记录为数组和索引(稍后您可以使用原始内存位置做一些有趣的事情,但我们现在不这样做)。x您可以通过在类中创建属性 aproperty并将其数据存储在同名的实例属性中来保持几乎完全相同的接口: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), P(np_x, 2), P(np_x, 3)]现在,您的所有更改都是相互透明的,因为您共享缓冲区:>>> obj_lst[0].x = 10>>> np_xarray([10,  3,  4,  5])>>> np_x[-2] = 20>>> obj_lst[10, 3, 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'), P(d_x, 'c'), P(d_x, 'd')]>>> obj_lst[0].x = 10>>> d_x{'a': 10, 'b': 3, 'c': 20, 'd': 5}>>> d_x['c'] = 20>>> obj_lst[10, 3, 20, 5]您还可以向 numpy 数组提供复杂索引:>>> np_x = np.arange(10)>>> obj_lst = [P(np_x, 0), P(np_x, slice(1, None, 2)), P(np_x, [1, 2, 6, 8])]>>> obj_lst[0, [1 3 5 7 9], [1 2 6 8]]>>> obj_lst[-1].x = 100>>> np_xarray([  0, 100, 100,   3,   4,   5, 100,   7, 100,   9])>>> np_x[5:] = 20>>> obj_lst[0, [100   3  20  20  20], [100 100  20  20]]
随时随地看视频慕课网APP

相关分类

Python
我要回答