在操做數組的時候返回的不是視圖就是副本。python
副本:複製web
視圖:連接數組
副本是一個數據的完整拷貝,若是咱們對副本進行修改,它不會影響到原始數據,物理內存不在同一位置。app
視圖是數據的一個別稱或引用,經過該別稱或引用亦可訪問、操做原有數據,但原有數據不會產生拷貝。若是咱們對視圖進行修改,它會影響到原始數據,物理內存在同一位置。ide
視圖通常發生在:函數
- 一、numpy 的切片操做返回原數據的視圖。
- 二、調用 ndarray 的 view() 函數產生一個視圖。
副本通常發生在:工具
- Python 序列的切片操做,調用deepCopy()函數。
- 調用 ndarray 的 copy() 函數產生一個副本。
賦值
賦值操做,兩個變量a, b都指向同一個內存地址, b與原始數組a的id()相同。 id()返回 Python 對象的通用標識符,相似於 C 中的指針。post
一個數組的任何變化都反映在另外一個數組上。 例如,一個數組的形狀改變也會改變另外一個數組的形狀。spa
import numpy as np a = np.arange(6) b = a print('數組a:',a) print('數組b:',b) print('a 調用 id() 函數:',id(a)) print('b 調用 id() 函數:',id(b)) b.shape = 3, 2 print('修改 b 的形狀:') print(b) print('a 的形狀也修改了:') print(a)
輸出結果爲:指針
數組a: [0 1 2 3 4 5]
數組b: [0 1 2 3 4 5]
a 調用 id() 函數: 2026424909056
b 調用 id() 函數: 2026424909056
修改 b 的形狀:
[[0 1]
[2 3]
[4 5]]
a 的形狀也修改了:
[[0 1]
[2 3]
[4 5]]
視圖或淺拷貝
Numpy的切片操做會返回原數據的視圖,切片產生的視圖是原視圖的一部分視圖,對視圖的修改會直接反映到原數據中,但它們的id是不一樣的。也就是說,視圖雖然指向原數據,可是他們和賦值引用仍是有區別的。
ndarray.view() 方會建立一個新的數組對象,該方法建立的新數組的維數更改不會更改原始數據的維數。
import numpy as np # 最開始 a 是個 3X2 的數組 a = np.arange(6).reshape(3, 2) print('數組 a:') print(a) print('\n') b = a.view() print('建立 a 的視圖b:') print(b) print('\n') print('a 的 id():',id(a)) print('b 的 id():',id(b)) print('\n') # 修改 b 的形狀,並不會修改 a b.shape = 2, 3 print('修改形狀後的b:') print(b) print('\n') print('修改b形狀後的a:') print(a)
輸出結果爲:
數組 a:
[[0 1]
[2 3]
[4 5]]
建立 a 的視圖b:
[[0 1]
[2 3]
[4 5]]
a 的 id(): 1601808711552
b 的 id(): 1601809504256
修改形狀後的b:
[[0 1 2]
[3 4 5]]
修改b形狀後的a:
[[0 1]
[2 3]
[4 5]]
使用切片建立視圖修改數據會影響到原始數組:
import numpy as np arr = np.arange(12) print('咱們的數組:',arr) print('\n') a = arr[3:] b = arr[3:] print('切片a:',a) print('切片b:',b) print('\n') a[1] = 123 b[2] = 234 print('修改後的數組arr:') print(arr) print('修改後的數組a:') print(a) print('修改後的數組b:') print(b) print('\n') print('a的id:',id(a)) print('b的id:',id(b)) print('arr的id:',id(arr))
輸出結果爲:
咱們的數組: [ 0 1 2 3 4 5 6 7 8 9 10 11]
切片a: [ 3 4 5 6 7 8 9 10 11]
切片b: [ 3 4 5 6 7 8 9 10 11]
修改後的數組arr:
[ 0 1 2 3 123 234 6 7 8 9 10 11]
修改後的數組a:
[ 3 123 234 6 7 8 9 10 11]
修改後的數組b:
[ 3 123 234 6 7 8 9 10 11]
a的id: 1173376024448
b的id: 1173376023968
arr的id: 1173376023888
變量 a,b 都是 arr 的一部分視圖,對視圖的修改會直接反映到原數據中。可是咱們觀察 a,b 的 id,他們是不一樣的,也就是說,視圖雖然指向原數據,可是他們和賦值引用仍是有區別的。
副本或深拷貝
ndarray.copy() 建立一個副本。 對副本數據進行修改,不會影響到原始數據,它們物理內存不同。
import numpy as np a = np.array([[10, 10], [2, 3], [4, 5]]) print('數組 a:') print(a) print('\n') b = a.copy() print('建立 a 的副本數組 b:') print(b) print('\n') # b 與 a 不共享任何內容 print('咱們可以寫入 b 來寫入 a 嗎?') print(b is a) print('\n') b[0, 0] = 100 print('修改副本b:') print(b) print('\n') print('修改副本b後,a數組不變:') print(a)
輸出結果爲:
數組 a:
[[10 10]
[ 2 3]
[ 4 5]]
建立 a 的副本數組 b:
[[10 10]
[ 2 3]
[ 4 5]]
咱們可以寫入 b 來寫入 a 嗎?
False
修改副本b:
[[100 10]
[ 2 3]
[ 4 5]]
修改副本b後,a數組:
[[10 10]
[ 2 3]
[ 4 5]]