日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python?numpy視圖與副本_python

作者:盆友圈的小可愛 ? 更新時間: 2022-04-06 編程語言

前言:

繼上一篇對numpy 模塊之ndarray一文中對 ndarray 內存結構主要分為兩部分:

metdata :存放數組類型dtype、數組維度ndim、維度數量shape、維間距strides等
raw bata:存放原始數據data

metdata 中包含著關于數組相關信息,可以幫助我們在數組ndarray中快速索引和解釋指定的數據

除此了對數組進行索引操作外,也會對數組的原數據進行類似與之前“拷貝”操作。

眾所周知,在 Python 中大家應該對深淺拷貝有一定的印象吧,在 numpy 中則換成了“視圖”與“副本”的概念了。

相信大家和我一樣對此存在疑問,十萬個為什么涌上心頭了,“視圖是什么?”,“什么是副本?”

因此,本期我們一起來學習 numpy 模塊中比較新奇的概念視圖與副本,Let's go~

1. 簡單講解

我們之前在學習 Python 賦值、深淺拷貝時,在代碼添加中對比兩個對象的地址id()是否一致。

同理,按照這樣的思路,numpy 中也可以對比兩個數組地址是否一樣。

同時,在 numpy 數組對象ndarray 也提供許多字段,方便讓我們進一步地查看數組內部的差異

ndarray.flags : 查看數組存儲策略、讀寫權限、對象等

  • C_CONTIGUOUS (C) 行優先存儲
  • F_CONTIGUOUS 列優先存儲
  • OWNDATA 數據所有者
  • WRITEABLE 編寫權限
  • ALIGNED 數據元素與硬件指針對齊
  • WRITEBACKIFCOPY 數組是其他數組的副本
  • UPDATEIFCOPY 已棄用

注:flags 相關屬性名稱可以單獨調用例如 flags.writeable

  • ndarray.base : 查看數組中的元素是否來自其他數組
  • ndarray.nbytes: 查看數組中數據占用的字節數
  • getsizeof(item): 查看數組占用的內存空點

介紹完上述指標,我們來小試一下:

>>> import numpy as np
>>> a = np.array([1,2,3,4])
>>> print(a[1:3])
[2 3]
>>> print(a[[1,2]])
[2 3]
>>>

查看a[1:3] 與 a[[1,2]] 內存地址,它們倆位置不一樣,a[[1,2]]意味發生了深拷貝本(副本),a[1:3] 是原數組a引用(視圖)

>>> print(id(a[1:3]))
2247482965008
>>> print(id(a[[1,2]]))
2247482964928

查看ndarray.owndata 屬性,發現a[1:3] 數據來自a數組的,而a[[1,2]]是自身數據的

>>> print(a.flags.owndata)
True
>>> print(a[1:3].flags.owndata)
False
>>> print(a[[1,2]].flags.owndata)
True

我們在看一下 ndarray.base 屬性,果真印證了使用flags.owndata 查詢的結果,a[1:3] 不是數據所有者,而數據來源數組a;

a[[1,2]] 是數據所有者,數據來源本身(None)

>>> print(a[[1,2]].base)
None
>>> print(a[1:3].base)
[1 2 3 4]

2. 視圖

視圖概念

我們通過上述簡單例子,可以知道 a[1:3] 不是數據所有者,數據來源于對數組a的引用(淺拷貝)。

因此,我們應該對視圖有了基本的認識了,看一下官方怎么描述視圖的

No copy at All。 Simple assignments make no copy of objects or their data.

視圖,是對原數組進行引用拷貝,共享原始數組的數據。

視圖應用

視圖在numpy中廣泛使用,視圖一般產生有兩種場景:

  • 當對原始數組進行引用時
  • 當自身無數據,與原數組共享數據時
>>> import numpy as np
>>> a = np.array([1,2,3,4])
>>> b = a
>>> b is a
True
>>> id(a)
2247207679680
>>> id(b)
2247207679680
>>>

我們可以看到 a 與 b 是 同享同一個數據空間的

numpy 模塊諸如索引、切片、函數view(),reshape()等返回視圖結果

>>> arr = np.arange(10)
>>> arr_view = arr.view()
>>> arr.shape = (2,5)
>>> arr_reshape = arr.reshape(5,2)
# ndarray.base 屬性
>>> print(arr.base)
None
>>> print(arr_view.base)
[[0 1 2 3 4]
?[5 6 7 8 9]]
>>> print(arr_reshape.base)
[[0 1 2 3 4]
?[5 6 7 8 9]]
# ndarray.flags.owndata 屬性
>>> print(arr.flags.owndata)
True
>>> print(arr_view.flags.owndata)
False
>>> print(arr_reshape.flags.owndata)
False
>>>

視圖優點

在 numpy 中 視圖可以創建的對象可以節省內存空間,并且無需復制,提高查詢速度

在視圖中,創建的對象如果修改數據,原始數據也被修改。

3. 副本

副本概念

副本是對原數組進行完整拷貝(數據地址也會拷貝新的),與原始數組完全獨立,相對于“深拷本”,不與原始數組共享數據。

同樣截取官網,對副本的描述:

Deep Copy The copy method makes a complete copy of the array and its data

當改變副本的數據元素值時,雖然改變了副本與原數組相互獨立,原始數組中元素值不會發生改變。

副本應用

  • 當進行切片操作時
  • 當需要與原始數組數據獨立時

副本的實現我們可以直接使用 ndarray.copy()方法對原數組進行深拷貝

b = np.array([2,5,7])

c = b.copy()

c[1] = 8

print("b:",b)
print("c:",c)

print("c is b:",c is b)

# 查看 ndarray.base 屬性?
print("b.base:",b.base)
print("c.base:",c.base)

# 查看 ndarray.flags.owndata
print("b.flags.owndata:",b.flags.owndata)
print("c.flags.owndata:",c.flags.owndata)

image.png

image.png

總結:

本期,我們對 numpy 模塊中重要的概念視圖和副本。

  • 視圖,相當于淺拷貝,與原數組共享數據。
  • 副本,相當于深拷貝,與原數組數據相互獨立

我們可以通過內存地址id()方法,同時借助ndarray.base、ndarray.flags來進一步分析區別

原文鏈接:https://juejin.cn/post/7054947502562213924

欄目分類
最近更新