天天看點

NumPy 副本和視圖

副本是一個資料的完整的拷貝,如果我們對副本進行修改,它不會影響到原始資料,實體記憶體不在同一位置。

視圖是資料的一個别稱或引用,通過該别稱或引用亦便可通路、操作原有資料,但原有資料不會産生拷貝。如果我們對視圖進行修改,它會影響到原始資料,實體記憶體在同一位置。

視圖一般發生在:

  • 1、numpy 的切片操作傳回原資料的視圖。
  • 2、調用 ndarray 的 view() 函數産生一個視圖。

副本一般發生在:

  • Python 序列的切片操作,調用deepCopy()函數。
  • 調用 ndarray 的 copy() 函數産生一個副本。

無複制

簡單的指派不會建立數組對象的副本。 相反,它使用原始數組的相同id()來通路它。 id()傳回 Python 對象的通用辨別符,類似于 C 中的指針。

此外,一個數組的任何變化都反映在另一個數組上。 例如,一個數組的形狀改變也會改變另一個數組的形狀。

執行個體

import numpy as np

a = np.arange(6)

print ('我們的數組是:')

print (a)

print ('調用 id() 函數:')

print (id(a))

print ('a 指派給 b:')

b = a

print (b)

print ('b 擁有相同 id():')

print (id(b))

print ('修改 b 的形狀:')

b.shape = 3,2

print ('a 的形狀也修改了:')

輸出結果為:

我們的數組是:
[0 1 2 3 4 5]
調用 id() 函數:
4349302224
a 指派給 b:
[0 1 2 3 4 5]
b 擁有相同 id():
4349302224
修改 b 的形狀:
[[0 1]
 [2 3]
 [4 5]]
a 的形狀也修改了:
[[0 1]
 [2 3]
 [4 5]]      

視圖或淺拷貝

ndarray.view() 方會建立一個新的數組對象,該方法建立的新數組的維數變化不會改變原始資料的維數。

# 最開始 a 是個 3X2 的數組

a = np.arange(6).reshape(3,2)

print ('數組 a:')

print ('建立 a 的視圖:')

b = a.view()

print ('兩個數組的 id() 不同:')

print ('a 的 id():')

print ('b 的 id():' )

# 修改 b 的形狀,并不會修改 a

b.shape = 2,3

print ('b 的形狀:')

print ('a 的形狀:')

數組 a:
[[0 1]
 [2 3]
 [4 5]]
建立 a 的視圖:
[[0 1]
 [2 3]
 [4 5]]
兩個數組的 id() 不同:
a 的 id():
4314786992
b 的 id():
4315171296
b 的形狀:
[[0 1 2]
 [3 4 5]]
a 的形狀:
[[0 1]
 [2 3]
 [4 5]]      

使用切片建立視圖修改資料會影響到原始數組:

arr = np.arange(12)

print ('我們的數組:')

print (arr)

print ('建立切片:')

a=arr[3:]

b=arr[3:]

a[1]=123

b[2]=234

print(arr)

print(id(a),id(b),id(arr[3:]))

我們的數組:
[ 0  1  2  3  4  5  6  7  8  9 10 11]
建立切片:
[  0   1   2   3 123 234   6   7   8   9  10  11]
4545878416 4545878496 4545878576      

變量 a,b 都是 arr 的一部分視圖,對視圖的修改會直接反映到原資料中。但是我們觀察 a,b 的 id,他們是不同的,也就是說,視圖雖然指向原資料,但是他們和指派引用還是有差別的。

副本或深拷貝

ndarray.copy() 函數建立一個副本。 對副本資料進行修改,不會影響到原始資料,它們實體記憶體不在同一位置。

a = np.array([[10,10], [2,3], [4,5]])

print ('建立 a 的深層副本:')

b = a.copy()

print ('數組 b:')

# b 與 a 不共享任何内容

print ('我們能夠寫入 b 來寫入 a 嗎?')

print (b is a)

print ('修改 b 的内容:')

b[0,0] = 100

print ('修改後的數組 b:')

print ('a 保持不變:')

數組 a:
[[10 10]
 [ 2  3]
 [ 4  5]]
建立 a 的深層副本:
數組 b:
[[10 10]
 [ 2  3]
 [ 4  5]]
我們能夠寫入 b 來寫入 a 嗎?
False
修改 b 的内容:
修改後的數組 b:
[[100  10]
 [  2   3]
 [  4   5]]
a 保持不變:
[[10 10]
 [ 2  3]
 [ 4  5]]      

更多相關文章

Python 直接指派、淺拷貝和深度拷貝解析