Python 如何在不隐藏额外内存分配的情况下就地修改numpy数组?

Python 如何在不隐藏额外内存分配的情况下就地修改numpy数组?,python,arrays,numpy,Python,Arrays,Numpy,我有一个函数,它必须用f(x)替换numpy数组x的每个元素x 但这不起作用: >>> X = numpy.random.random( size=(2,3) ) >>> X array([[ 0.97476386, 0.76411101, 0.37690288], [ 0.05462798, 0.44722799, 0.23570353]]) >>>> modify_inplace(X) >>>

我有一个函数,它必须用f(x)替换numpy数组x的每个元素x

但这不起作用:

>>> X = numpy.random.random( size=(2,3) )
>>> X
array([[ 0.97476386,  0.76411101,  0.37690288],
       [ 0.05462798,  0.44722799,  0.23570353]])
>>>> modify_inplace(X)
>>> X
array([[ 0.97476386,  0.76411101,  0.37690288],
       [ 0.05462798,  0.44722799,  0.23570353]])
我知道,我可以简单地返回新的数组,但我想知道是否可以修改原地的numpy数组,这样就不会分配额外的内存了


Ashwini Chaudhary在下面提供了一个解决方案,但这并不是我想要的,因为我需要在没有任何额外malloc的情况下修改数组。

目前,您只需创建一个新的局部变量
X
,并为其分配一个新值,要更新函数中由
X
指向的对象,请使用切片分配[:]

>>> def modify_inplace(X):
        X[:] = 2. / (8. + numpy.exp(-X))
...     
>>> X = numpy.random.random( size=(2,3))
>>> X
array([[ 0.21210661,  0.03573271,  0.07002263],
       [ 0.77282535,  0.13973994,  0.82784145]])
>>> modify_inplace(X)
>>> X
array([[ 0.22704366,  0.22309233,  0.22390467],
       [ 0.23635894,  0.22548971,  0.23705132]])

这种情况下的真正就地方法可以是:

def modify_inplace(X):
    np.exp(X, out=X)
    X += 8.
    np.power(X, -1, out=X)
    X *= 2
与@Ashwini Chaudhary的方法相比,有两个主要优势(这也是很好的):

  • 不需要分配新阵列
  • 操作后无需复制任何数据

编辑:

请注意,对于
X
多次出现的更复杂表达式,很难避免复制,例如:

(X + 2.)/(8. + np.exp(X))

这里,当您将
X
更改为计算
np.exp(X)
时,计算表达式的其余部分将不再有效…

谢谢。因此,在这种情况下,Numpy不会分配任何额外的存储空间?@psihodelia对于您的情况,将首先在内存中创建一个新数组,然后用该数组替换原始数组的内容。之后,新数组将被垃圾收集,因为不再有对它的引用。但这意味着此数组不会在原地修改。我的问题是如何避免内存分配和修改数组-就像在C中一样。无论如何,谢谢你。@psihodelia如果你想这样做,是O(1)个额外的内存,那么你必须用一个简单的循环替换RHS上的表达式,然后在循环过程中,用迭代中生成的值更新X中的当前项。谢谢。在使用两个X的第二个示例中,还有什么解决方案可以避免内存分配?@psihodelia在这种情况下,我只看到在数组上循环计算临时变量中表达式的答案并替换旧值。。。例如,可以在Cython中完成
(X + 2.)/(8. + np.exp(X))