在使用 NumPy 進(jìn)行數(shù)據(jù)處理時,數(shù)組對象不僅可以被讀取或修改,還經(jīng)常需要在不同變量或不同數(shù)組之間進(jìn)行“復(fù)制”。例如:將一個數(shù)組賦值給另一個變量、通過切片獲取數(shù)組的一部分、或顯式創(chuàng)建新的數(shù)組副本。
需要注意的是,這些操作在語法上都表現(xiàn)為“復(fù)制”,但在內(nèi)存層面的行為卻可能完全不同。
NumPy 數(shù)組由數(shù)據(jù)緩沖區(qū)(data buffer)與數(shù)組結(jié)構(gòu)信息(shape、strides、dtype 等)兩部分構(gòu)成。不同“復(fù)制方式”的本質(zhì)差異,在于這兩部分是否被共享。
從內(nèi)存共享的角度來看,NumPy 中數(shù)組之間的關(guān)系可以分為三類:
(1)引用(reference)
(2)視圖(view)
(3)副本(copy)
理解這三種關(guān)系,是掌握 NumPy 數(shù)組行為的重要基礎(chǔ)。
一、數(shù)組引用(Reference)
在 Python 中,如果將一個數(shù)組賦值給另一個變量:
b = a此時并不會創(chuàng)建新的數(shù)組對象,而只是創(chuàng)建了一個新的變量名指向同一個數(shù)組。
示例:
print(a)輸出:
[ 4 5 6]]該行為本質(zhì)上屬于引用(別名)綁定,而非拷貝。
變量 a 與 b 指向的是同一個數(shù)組對象,因此修改任意一方都會影響另一方。
可以通過 函數(shù)查看對象標(biāo)識:
print(id(b))兩個變量對應(yīng)的對象標(biāo)識是相同的。
二、數(shù)組視圖(View)
NumPy 提供了一種重要機(jī)制:視圖(view)。
視圖是一個新的數(shù)組對象,它與原數(shù)組共享底層數(shù)據(jù)緩沖區(qū)。即:
? 數(shù)據(jù)共享
? 數(shù)組結(jié)構(gòu)獨立(shape、strides 通常獨立)
因此:
? 修改視圖的數(shù)據(jù),會影響原數(shù)組的數(shù)據(jù)
? 修改視圖的結(jié)構(gòu),通常不影響到原數(shù)組
需要注意的是,雖然視圖通常具有獨立的結(jié)構(gòu)信息,但在某些操作中(如直接修改屬性),仍需謹(jǐn)慎處理結(jié)構(gòu)一致性。
這種設(shè)計的目的在于:
? 提高內(nèi)存利用率
? 避免不必要的數(shù)據(jù)復(fù)制
? 提升大規(guī)模數(shù)組計算效率
1、創(chuàng)建視圖的常用方法
view()
創(chuàng)建當(dāng)前數(shù)組的數(shù)據(jù)視圖,新數(shù)組對象與原數(shù)組共享底層數(shù)據(jù)。
ndarray.view(dtype=None, type=None)參數(shù)說明:
? dtype:可選,指定新的數(shù)據(jù)類型
? type:可選,指定返回數(shù)組的子類
返回值:
返回一個新的 ndarray 對象(共享數(shù)據(jù))。
示例:
print(a)輸出:
[ 4 5 6]]雖然 a 與 b 是不同的數(shù)組對象,但它們共享同一塊數(shù)據(jù)內(nèi)存,因此修改其中一個數(shù)組會影響另一個數(shù)組。
2、返回視圖的常見操作
(1)切片
在 NumPy 中,基本索引(切片)通常返回視圖。
示例:
print(a)輸出:
[ 4 5 6]]數(shù)組 b 是 a 的切片視圖,因此修改 b 的數(shù)據(jù)會影響原數(shù)組。
(2)數(shù)組形狀重構(gòu)時
在不改變數(shù)據(jù)內(nèi)容的情況下,使用 reshape() 重新解釋數(shù)組的形狀。多數(shù)情況下返回視圖。
示例:
print(a)輸出:
[100 1 2 3 4 5]reshape() 在大多數(shù)情況下返回視圖,因此 b 與 a 共享數(shù)據(jù)內(nèi)存。修改 b 會反映到原數(shù)組 a 上。
(3)展平數(shù)組時
使用 numpy.ravel() 將數(shù)組展平為一維數(shù)組時,優(yōu)先返回視圖。
示例:
print(a)輸出:
[ 4 5 6]]三、數(shù)組副本(Copy)
如果希望獲得一個完全獨立的數(shù)組,則需要創(chuàng)建數(shù)組副本。
1、顯式創(chuàng)建數(shù)組副本
NumPy 提供了 ndarray.copy() 和 numpy.copy() 兩種復(fù)制方法。
ndarray.copy()
創(chuàng)建數(shù)組的完整副本,復(fù)制底層數(shù)據(jù),新數(shù)組與原數(shù)組的數(shù)據(jù)完全獨立。
ndarray.copy(order='C')參數(shù)說明:
? order:內(nèi)存布局方式(默認(rèn)為 'C')
返回值:
返回一個新的獨立的 ndarray 數(shù)組對象。
示例:
print(a)輸出:
[4 5 6]]數(shù)組 b 是 a 的數(shù)據(jù)副本,因此修改 b 不會影響 a。
numpy.copy()
返回輸入數(shù)組的副本。
numpy.copy(a)參數(shù)說明:
? a:輸入數(shù)組
返回值:
返回一個新的獨立的 ndarray 數(shù)組對象。
示例:
print(a)輸出:
[4 5 6]]函數(shù) numpy.copy() 與 ndarray.copy() 的行為基本一致。
2、返回副本的常見操作
(1)高級索引時
當(dāng)使用整數(shù)數(shù)組或布爾數(shù)組進(jìn)行高級索引時,返回副本,不共享底層數(shù)據(jù)。
示例:
print(a)輸出:
[4 5 6]]雖然語法類似切片,但因使用整數(shù)數(shù)組索引,返回副本。
需要注意的是,是否返回視圖,并不取決于語法形式,而取決于索引類型。只要使用整數(shù)數(shù)組或布爾數(shù)組,即屬于高級索引,將返回副本。
(2)展平數(shù)組時
使用 ndarray.flatten() 將數(shù)組展平為一維數(shù)組時,始終復(fù)制數(shù)據(jù)。
示例:
print(a)輸出:
[4 5 6]]flatten() 會返回數(shù)組副本,因此修改 b 不會影響原數(shù)組 a。
四、淺拷貝與深拷貝
在 Python 中,對象復(fù)制通常分為淺拷貝(shallow copy)和深拷貝(deep copy)兩種方式,通常通過 實現(xiàn):
copy.deepcopy()但對于 NumPy 數(shù)組來說,情況略有不同。
由于 NumPy 數(shù)組的數(shù)據(jù)通常存儲在連續(xù)的內(nèi)存塊 中,因此 ndarray.copy() 通常已經(jīng)復(fù)制了數(shù)組數(shù)據(jù),在大多數(shù)情況下,它的行為相當(dāng)于 深拷貝。
例如:
b = a.copy()此時兩個數(shù)組的數(shù)據(jù)完全獨立。
需要注意的是,如果數(shù)組的元素類型 dtype 為 object,則數(shù)組中存儲的是 Python 對象引用。在這種情況下,ndarray.copy() 只會復(fù)制數(shù)組結(jié)構(gòu),而不會遞歸復(fù)制對象本身,因此仍可能出現(xiàn)淺拷貝行為。
五、判斷是否共享內(nèi)存
NumPy 提供了兩個函數(shù),用于判斷數(shù)組之間是否共享內(nèi)存。
numpy.shares_memory()
判斷兩個數(shù)組是否共享同一塊內(nèi)存。
numpy.shares_memory(a, b)返回值:
返回布爾值。
numpy.may_share_memory()與其基本一致,但基于保守判斷,判斷兩個數(shù)組是否可能共享內(nèi)存。
示例:
print(np.shares_memory(a, b))輸出:
True數(shù)組 b 是 a 的切片視圖,因此兩者共享數(shù)據(jù)內(nèi)存。
如果數(shù)組是通過 copy() 創(chuàng)建:
np.shares_memory(a,c)輸出:
False說明兩個數(shù)組的數(shù)據(jù)不共享內(nèi)存,彼此獨立。
小結(jié)
NumPy 中的“復(fù)制”涉及數(shù)據(jù)緩沖區(qū)與數(shù)組結(jié)構(gòu)兩個層面。變量賦值僅創(chuàng)建引用;切片與 view 通常生成共享數(shù)據(jù)的視圖;而 copy() 等操作才會復(fù)制底層數(shù)據(jù)。理解這些機(jī)制,有助于避免隱式數(shù)據(jù)修改,并提升數(shù)組計算的效率。
“點贊有美意,贊賞是鼓勵”
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.