>>> 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]])
很明显为什么会这样:当我键入 t = ..
时,我只是将 t
与内存中的其他数据“重新链接”。但问题是:
- 我如何破解它并传递对子矩阵的引用?和
- 仍然能够更改此子矩阵的值吗?
最佳答案
- how I can ... pass reference to the submatrix out of function?
简单地说,您不能像在 C++ 中那样从 Python 中的函数调用返回左值。在您的情况下,Python 假定您将一个值直接分配给 sub(a)
,这是一个函数调用,而不是分配给它返回的对象。
当然,您可以使用 Indexing 来获取对原始对象的引用,如后所述。这将允许您更改原始矩阵的一部分。
- and still be able to change this submatrixes values?
您可以在函数内部更改数组子矩阵的值,如下所示:
def sub(a):
a[:2, :2] = np.arange(4).reshape((2,2))
return a[:2, :2]
这不仅会返回
修改后的子矩阵,还会更改数组本身。
对象是按引用传递的,但它们的引用是按值传递的:
就像Java一样,Python是按值传递的,所以所有的对象都是作为引用传递给函数的,而这些引用都是按值传递的。
所以当你索引这个数组对象并在函数内部修改它的值时,你是在修改这个引用指向的内存位置的值,但是如果你改变引用本身那么它不会修改原始对象因为它的引用仅按值传递。
使用索引按值传递对对象的引用:
按照这个解释,您甚至可以更进一步,通过值从函数返回对象的引用,并在函数外部使用它修改矩阵:
- 调用函数
sub(a)
,它将按值返回对子矩阵的引用,子矩阵本身就是对按值传递的原始矩阵的引用。 - 将此函数调用分配给另一个变量,该变量将按值将对子矩阵的引用传递给此新变量,
x = sub(a)
- 索引此子矩阵以选择其所有内容并修改它们的值:
x[:] = np.ones((2,2))
这也将修改原始矩阵
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]])
OR,作为快捷方式:
>>> sub(a)[:] = np.ones((2,2)) >>> a array([[1, 1, 2], [1, 1, 5], [6, 7, 8]])
更改引用不会更改对象:
但是,现在如果您将变量
x
设置为np.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]])
关于python - 从 numpy 中的函数返回对子矩阵的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25798843/