上一篇文章: Python標準庫---1三、內置類型:二進制序列類型 ( bytes, bytearray)
下一篇文章: Python標準庫---1五、內置類型:集合類型、映射類型
memoryview 對象容許 Python 代碼訪問一個對象的內部數據,只要該對象支持 緩衝區協議 而無需進行拷貝。segmentfault
建立一個引用 obj 的 memoryview。 obj 必須支持緩衝區協議。 支持緩衝區協議的內置對象包括 bytes 和 bytearray。數組
memoryview 具備 元素 的概念,即由原始對象 obj 所處理的基本內存單元。 對於許多簡單類型例如 bytes 和 bytearray 來講,一個元素就是一個字節,可是其餘的類型例如 array.array 可能有更大的元素。ide
len(view) 與 tolist 的長度相等。 若是 view.ndim = 0,則其長度爲 1。 若是 view.ndim = 1,則其長度等於 view 中元素的數量。 對於更高的維度,其長度等於表示 view 的嵌套列表的長度。 itemsize 屬性可向你給出單個元素所佔的字節數。spa
memoryview 支持經過切片和索引訪問其元素。 一維切片的結果將是一個子視圖:3d
>>> v = memoryview(b'abcefg') >>> v[1] 98 >>> v[-1] 103 >>> v[1:4] <memory at 0x7f3ddc9f4350> >>> bytes(v[1:4]) b'bce'
若是 format 是一個來自於 struct 模塊的原生格式說明符,則也支持使用整數或由整數構成的元組進行索引,並返回具備正確類型的單個 元素。 一維內存視圖可使用一個整數或由一個整數構成的元組進行索引。 多維內存視圖可使用由剛好 ndim 個整數構成的元素進行索引,ndim 即其維度。 零維內存視圖可使用空元組進行索引。code
這裏是一個使用非字節格式的例子:
>>> import array >>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444]) >>> m = memoryview(a) >>> m[0] -11111111 >>> m[-1] 44444444 >>> m[::2].tolist() [-11111111, -33333333]
若是下層對象是可寫的,則內存視圖支持一維切片賦值。 改變大小則不被容許:orm
>>> data = bytearray(b'abcefg') >>> v = memoryview(data) >>> v.readonly False >>> v[0] = ord(b'z') >>> data bytearray(b'zbcefg') >>> v[1:4] = b'123' >>> data bytearray(b'z123fg') >>> v[2:3] = b'spam' Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: memoryview assignment: lvalue and rvalue have different structures >>> v[2:6] = b'spam' >>> data bytearray(b'z1spam')
由帶有格式符號 'B', 'b' 或 'c' 的可哈希(只讀)類型構成的一維內存視圖一樣是可哈希的。 哈希定義爲 hash(m) == hash(m.tobytes()):對象
>>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') True >>> hash(v[2:4]) == hash(b'ce') True >>> hash(v[::-2]) == hash(b'abcefg'[::-2]) True
在 3.3 版更改: 一維內存視圖如今能夠被切片。 帶有格式符號 'B', 'b' 或 'c' 的一維內存視圖如今是可哈希的。索引
在 3.4 版更改: 內存視圖如今會自動註冊爲 collections.abc.Sequence內存
在 3.5 版更改: 內存視圖如今可以使用整數元組進行索引。
memoryview 具備如下一些方法:
memoryview 與 PEP 3118 中的導出器這二者若是形狀相同,而且若是當使用 struct 語法解讀操做數的相應格式代碼時全部對應值都相同,則它們就是等價的。
對於 tolist() 當前所支持的 struct 格式字符串子集,若是 v.tolist() == w.tolist() 則 v 和 w 相等:
>>> import array >>> a = array.array('I', [1, 2, 3, 4, 5]) >>> b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0]) >>> c = array.array('b', [5, 3, 1]) >>> x = memoryview(a) >>> y = memoryview(b) >>> x == a == y == b True >>> x.tolist() == a.tolist() == y.tolist() == b.tolist() True >>> z = y[::-2] >>> z == c True >>> z.tolist() == c.tolist() True
若是兩邊的格式字符串都不被 struct 模塊所支持,則兩對象比較結果老是不相等(即便格式字符串和緩衝區內容相同):
>>> from ctypes import BigEndianStructure, c_long >>> class BEPoint(BigEndianStructure): ... _fields_ = [("x", c_long), ("y", c_long)] ... >>> point = BEPoint(100, 200) >>> a = memoryview(point) >>> b = memoryview(point) >>> a == point False >>> a == b False
請注意,與浮點數的狀況同樣,對於內存視圖對象來講,v is w 也 並不 意味着 v == w。
在 3.3 版更改: 以前的版本比較原始內存時會忽略條目的格式與邏輯數組結構。
將緩衝區中的數據做爲字節串返回。 這至關於在內存視圖上調用 bytes 構造器。
>>> m = memoryview(b"abc") >>> m.tobytes() b'abc' >>> bytes(m) b'abc'
對於非連續數組,結果等於平面化表示的列表,其中全部元素都轉換爲字節串。 tobytes() 支持全部格式字符串,不符合 struct 模塊語法的那些也包括在內。
返回一個字符串對象,其中分別以兩個十六進制數碼錶示緩衝區裏的每一個字節。
>>> m = memoryview(b"abc") >>> m.hex() '616263'
3.5 新版功能.
將緩衝區內的數據以一個元素列表的形式返回。
>>> memoryview(b'abc').tolist() [97, 98, 99] >>> import array >>> a = array.array('d', [1.1, 2.2, 3.3]) >>> m = memoryview(a) >>> m.tolist() [1.1, 2.2, 3.3]
在 3.3 版更改: tolist() 如今支持 struct 模塊語法中的全部單字符原生格式以及多維表示形式。
釋放由內存視圖對象所公開的底層緩衝區。 許多對象在被視圖所獲取時都會採起特殊動做(例如,bytearray 將會暫時禁止調整大小);所以,調用 release() 能夠方便地儘早去除這些限制(並釋聽任何多餘的資源)。
在此方法被調用後,任何對視圖的進一步操做將引起 ValueError (release() 自己除外,它能夠被屢次調用):
>>> m = memoryview(b'abc') >>> m.release() >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object 使用 with 語句,能夠經過上下文管理協議達到相似的效果: >>> >>> with memoryview(b'abc') as m: ... m[0] ... 97 >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object
3.2 新版功能.
將內存視圖轉化爲新的格式或形狀。 shape 默認爲 [byte_length//new_itemsize],這意味着結果視圖將是一維的。 返回值是一個新的內存視圖,但緩衝區自己不會被複制。 支持的轉化有 1D -> C-contiguous 和 C-contiguous -> 1D。
目標格式僅限於 struct 語法中的單一元素原生格式。 其中一種格式必須爲字節格式 ('B', 'b' 或 'c')。 結果的字節長度必須與原始長度相同。
將 1D/long 轉換爲 1D/unsigned bytes:
>>> import array >>> a = array.array('l', [1,2,3]) >>> x = memoryview(a) >>> x.format 'l' >>> x.itemsize 8 >>> len(x) 3 >>> x.nbytes 24 >>> y = x.cast('B') >>> y.format 'B' >>> y.itemsize 1 >>> len(y) 24 >>> y.nbytes 24
將 1D/unsigned bytes 轉換爲 1D/char:
>>> b = bytearray(b'zyz') >>> x = memoryview(b) >>> x[0] = b'a' Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: memoryview: invalid value for format "B" >>> y = x.cast('c') >>> y[0] = b'a' >>> b bytearray(b'ayz')
將 1D/bytes 轉換爲 3D/ints 再轉換爲 1D/signed char:
>>> import struct >>> buf = struct.pack("i"*12, *list(range(12))) >>> x = memoryview(buf) >>> y = x.cast('i', shape=[2,2,3]) >>> y.tolist() [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] >>> y.format 'i' >>> y.itemsize 4 >>> len(y) 2 >>> y.nbytes 48 >>> z = y.cast('b') >>> z.format 'b' >>> z.itemsize 1 >>> len(z) 48 >>> z.nbytes 48
將 1D/unsigned char 轉換爲 2D/unsigned long:
>>> buf = struct.pack("L"*6, *list(range(6))) >>> x = memoryview(buf) >>> y = x.cast('L', shape=[2,3]) >>> len(y) 2 >>> y.nbytes 48 >>> y.tolist() [[0, 1, 2], [3, 4, 5]]
3.3 新版功能.
在 3.5 版更改: 當轉換爲字節視圖時,源格式將再也不受限。
還存在一些可用的只讀屬性:
內存視圖的下層對象:
>>> b = bytearray(b'xyz') >>> m = memoryview(b) >>> m.obj is b True
3.3 新版功能.
nbytes == product(shape) * itemsize == len(m.tobytes())。 這是數組在連續表示時將會佔用的空間總字節數。 它不必定等於 len(m):
>>> import array >>> a = array.array('i', [1,2,3,4,5]) >>> m = memoryview(a) >>> len(m) 5 >>> m.nbytes 20 >>> y = m[::2] >>> len(y) 3 >>> y.nbytes 12 >>> len(y.tobytes()) 12
多維數組:
>>> import struct >>> buf = struct.pack("d"*12, *[1.5*x for x in range(12)]) >>> x = memoryview(buf) >>> y = x.cast('d', shape=[3,4]) >>> y.tolist() [[0.0, 1.5, 3.0, 4.5], [6.0, 7.5, 9.0, 10.5], [12.0, 13.5, 15.0, 16.5]] >>> len(y) 3 >>> y.nbytes 96
3.3 新版功能.
一個代表內存是否只讀的布爾值。
一個字符串,包含視圖中每一個元素的格式(表示爲 struct 模塊樣式)。 內存視圖能夠從具備任意格式字符串的導出器建立,但某些方法 (例如 tolist()) 僅限於原生的單元素格式。
在 3.3 版更改: 格式 'B' 如今會按照 struct 模塊語法來處理。 這意味着 memoryview(b'abc')[0] == b'abc'[0] == 97。
memoryview 中每一個元素以字節表示的大小:
>>> import array, struct >>> m = memoryview(array.array('H', [32000, 32001, 32002])) >>> m.itemsize 2 >>> m[0] 32000 >>> struct.calcsize('H') == m.itemsize True
一個整數,表示內存所表明的多維數組具備多少個維度。
### shape
一個整數元組,經過 ndim 的長度值給出內存所表明的 N 維數組的形狀。
在 3.3 版更改: 當 ndim = 0 時值爲空元組而再也不爲 None。
一個整數元組,經過 ndim 的長度給出以字節表示的大小,以便訪問數組中每一個維度上的每一個元素。
在 3.3 版更改: 當 ndim = 0 時值爲空元組而再也不爲 None。
供 PIL 風格的數組內部使用。 該值僅做爲參考信息。
一個代表內存是否爲 C-contiguous 的布爾值。
3.3 新版功能.
一個代表內存是否爲 Fortran contiguous 的布爾值。 3.3 新版功能.
一個代表內存是否爲 contiguous 的布爾值。
3.3 新版功能.
上一篇文章: Python標準庫---1三、內置類型:二進制序列類型 ( bytes, bytearray)
下一篇文章: Python標準庫---1五、內置類型:集合類型、映射類型