从numpy函数返回对子矩阵的引用

Ben*_*man 5 python numpy reference function matrix

>>> a = np.arange(9).reshape((3, 3))
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> def sub(a):
...  return a[:2, :2]
... 
>>> sub(a)
array([[0, 1],
       [3, 4]])
>>> sub(a) = np.arange(4).reshape((2, 2))
  File "<stdin>", line 1
SyntaxError: cant assign to function call
>>> t = a[:2, :2]
>>> t = np.arange(4).reshape((2, 2))
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> a[:2, :2] = np.arange(4).reshape((2, 2))
>>> a
array([[0, 1, 2],
       [2, 3, 5],
       [6, 7, 8]])
Run Code Online (Sandbox Code Playgroud)

而且很明显为什么会这样:当我输入时t = ..,我只是'重新链接' t到内存中的其他数据.但问题是:

  1. 我怎么能破解它并将参考文献传递给子矩阵?和
  2. 还能改变这个子矩阵的价值吗?

Pac*_*ler 1

  1. 我怎样才能...传递对功能之外的子矩阵的引用?

简而言之,您无法像在 C++ 中那样从 Python 中的函数调用返回左值。在您的情况下,Python 假定您直接将值分配给sub(a),这是一个函数调用,而不是分配给它返回的对象。

当然,您可以使用索引来获取对原始对象的引用,如下所述。这将允许您更改原始矩阵的部分。

  1. 并且仍然能够更改这个子矩阵值?

您可以更改函数本身内部数组的子矩阵的值,如下所示:

def sub(a):
    a[:2, :2] = np.arange(4).reshape((2,2))
    return a[:2, :2]
Run Code Online (Sandbox Code Playgroud)

这不仅会return修改子矩阵,还会更改数组本身。


对象是按引用传递的,但它们的引用是按值传递的:

就像Java一样,Python是按值传递的,因此所有对象都作为引用传递到函数中,并且这些引用是按值传递的。

因此,当您索引此数组对象并在函数内修改其值时,您正在修改此引用指向的内存位置的值,但如果您更改引用本身,那么它不会修改原始对象,因为它的引用仅按值传递。

使用索引按值传递对对象的引用:

按照这个解释,您甚至可以更进一步,按值从函数返回对象的引用,并在函数外部使用它修改矩阵:

  1. 调用函数 ,sub(a)它将按值返回对子矩阵的引用,子矩阵本身就是对按值传递的原始矩阵的引用。
  2. 将对函数的调用分配给另一个变量,该变量会将对子矩阵的引用按值传递给这个新变量,x = sub(a)
  3. 索引该子矩阵以选择其所有内容并修改它们的值:x[:] = np.ones((2,2))
  4. 这也将修改原始矩阵,a因为您已经修改了内存中所引用的位置的值x

    >>> x = sub(a)
    >>> x[:] = np.ones((2,2))
    >>> x
    array([[1, 1],
           [1, 1]])
    >>> a
    array([[1, 1, 2],
           [1, 1, 5],
           [6, 7, 8]])
    
    Run Code Online (Sandbox Code Playgroud)

    或者,作为快捷方式:

    >>> sub(a)[:] = np.ones((2,2))
    >>> a
    array([[1, 1, 2],
           [1, 1, 5],
           [6, 7, 8]])
    
    Run Code Online (Sandbox Code Playgroud)

更改引用不会更改对象:

  1. 但是,现在如果您将变量设置xnp.ones((2,2))a不会更改,因为通过这样做,您正在更改按值传递的引用本身。

    >>> x = 2         # this won't change a because x is a reference passed by value
    >>> a
    array([[1, 1, 2],
           [1, 1, 5],
           [6, 7, 8]])
    
    Run Code Online (Sandbox Code Playgroud)