如何使NumPy数组的元素可设置属性?

3 投票
1 回答
2134 浏览
提问于 2025-04-18 14:16

我有一个Python对象的属性,它返回一个数组。现在,我可以设置这个属性的设置器,这样整个数组就可以被设置了。不过,我不太清楚如何让数组里的每个元素也能通过这个属性单独设置。

从用户的角度来看(假设有一个空的SomeClass类):

>>> x = SomeClass()
>>> x.array = [1, 2, 3]
>>> x.array[1] = 4
>>> print (x.array)
[1, 4, 3]

现在,假设SomeClass.array是定义为

class SomeClass(object):
    def __init__(self, a):
        self._a = a

    @property
    def array(self):
        return self._a
    @array.setter
    def array(self, a):
        self._a = a

一切仍然像上面那样工作。如果我强制在设置器中使用简单的NumPy数组也是可以的。

但是,如果我把return self._a替换成一个NumPy函数(这个函数会逐个处理元素),并把self._a = a替换成反向函数,那么当然,数组的内容就不会被设置了。

举个例子:

import numpy as np

class SomeClass(object):
    def __init__(self, a):
        self._a = np.array(a)

    @property
    def array(self):
        return np.sqrt(self._a)
    @array.setter
    def array(self, a):
        self._a = np.power(a, 2)

现在,用户看到的输出是:

>>> x = SomeClass([1, 4, 9])
>>> print (x.array)
array([1., 2., 3.])
>>> x.array[1] = 13
>>> print (x.array)    # would expect an array([1., 13., 3.]) now!
array([1., 2., 3.])

我想我明白问题出在哪里了(NumPy在操作过程中创建的数组的元素被改变了,但这对存储的数组没有影响)。

那么,如何正确实现SomeClass,使得数组的单个元素可以单独写入和设置呢?

非常感谢你的提示和帮助,TheXMA

@Jaime在他回答下提到的要点对我帮助很大!谢谢!

1 个回答

0

因为数组是可变对象,所以即使没有设置函数,我们也可以直接修改数组里的每个元素:

>>> class A(object):
...     def __init__(self, a):
...         self._a = np.asarray(a)
...     @property
...     def arr(self):
...         return self._a
...
>>> a = A([1,2,3])

>>> a.arr
array([1, 2, 3])

>>> a.arr = [4,5,6] # There is no setter...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

>>> a.arr[1] = 7 # ...but the array is mutable
>>> a.arr
array([1, 7, 3])

这就是元组和列表的一个区别,列表是可变的,可以修改,而元组则不可修改。总之,回答你的问题:想要修改单个元素其实很简单,只要你的获取函数返回的是对象本身。

至于你第二个例子中的更复杂的性能,似乎没有简单的方法可以实现。我觉得你可以通过让你的 SomeClass.array 属性成为一个自定义类来实现这个功能,这个类要么是 ndarray 的子类,要么是它的一个实例的包装。不管哪种方式,都需要做不少的工作。

撰写回答