簡體   English   中英

從numpy函數返回對子矩陣的引用

[英]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到存儲器中的其他數據。 但問題是:

  1. 我怎么能破解它並將參考文獻傳遞給子矩陣?
  2. 還能改變這個子矩陣的價值嗎?
  1. 我怎么能......將參考文獻傳遞給子矩陣?

簡單地說,你不能像在C ++中那樣從Python函數調用中返回l值。 在您的情況下,Python假定您直接將值賦給sub(a) ,這是一個函數調用,而不是它返回的對象。

在幕后,您可以使用索引來獲取對原始對象的引用,如稍后所述。 這將允許您更改原始矩陣的一部分。

  1. 並且仍然能夠更改此子矩陣值?

您可以在函數本身內更改數組子矩陣的值,如下所示:

def sub(a):
    a[:2, :2] = np.arange(4).reshape((2,2))
    return a[:2, :2]

這不僅會return修改后的子矩陣,還會更改數組本身。


對象是Pass-by-Reference,但它們的引用是按值傳遞:

就像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]]) 

    或者 ,作為捷徑:

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

更改引用不會更改對象:

  1. 但是,現在如果將變量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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM