[英]return reference to a submatrix from function in numpy
>>> 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
到存儲器中的其他數據。 但問題是:
- 我怎么能......將參考文獻傳遞給子矩陣?
簡單地說,你不能像在C ++中那樣從Python函數調用中返回l值。 在您的情況下,Python假定您直接將值賦給sub(a)
,這是一個函數調用,而不是它返回的對象。
在幕后,您可以使用索引來獲取對原始對象的引用,如稍后所述。 這將允許您更改原始矩陣的一部分。
- 並且仍然能夠更改此子矩陣值?
您可以在函數本身內更改數組子矩陣的值,如下所示:
def sub(a):
a[:2, :2] = np.arange(4).reshape((2,2))
return a[:2, :2]
這不僅會return
修改后的子矩陣,還會更改數組本身。
對象是Pass-by-Reference,但它們的引用是按值傳遞:
就像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]])
或者 ,作為捷徑:
>>> 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
的正確操作是:
In [97]: t=sub(a)
In [98]: t
Out[98]:
array([[0, 1],
[3, 4]])
In [100]: t[:]=np.arange(4).reshape(2,2)
In [101]: t
Out[101]:
array([[0, 1],
[2, 3]])
In [102]: a
Out[102]:
array([[0, 1, 2],
[2, 3, 5],
[6, 7, 8]])
該函數返回原始數組的view
,與在函數外部執行t = a[:2, :2]
。 t=...
重新分配變量,但t[:]=...
修改視圖的內容(數組元素)。 由於它是一個視圖,原始數組內容也會發生變化。 這與你a[:2, :2] =...
。
只要使用[:]
,就不需要中間變量賦值:
In [104]: sub(a)[:]=np.zeros((2,2))
In [105]: a
Out[105]:
array([[0, 0, 2],
[0, 0, 5],
[6, 7, 8]])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.