跳至內容

Python/字節數組

維基教科書,自由的教學讀本

Buffer Protocol是特定的Python對象,包裝了訪問內存數組或者緩衝區。包括內置類型:

  • bytes是只讀字節數組。
  • bytearray是可讀寫字節數組。
  • array.array
a=b"abc"  #创建bytes对象
bytes("汉字","utf-8") #创建bytes对象,解码方式为utf-8
b=bytearray(b"abc") #创建bytearray对象

與字符串一樣,支持append、extend、upper等方法,加法、乘法等運算。

bytes

[編輯]

class bytes([source[, encoding[, errors]]])構造函數,如

a=b'still allows embedded "double" quotes'

其他構造函數:

bytes(10)
bytes(range(20))
bytes(otherBytesObj)

類方法:

  • fromhex(string):以16進制解碼一個字符串,其中的空白符被忽略。如bytes.fromhex('2Ef0 F1f2 ')
  • hex([sep[, bytes_per_sep]]):把內容編碼為16進制數字組成的字符串。bytes_per_sep控制分隔符出現在哪個字節,正值從右數,負值從左數

bytearray

[編輯]

bytearray是可變的(mutable)版本,與只讀的bytes對應。

構造函數:

bytearray()
bytearray(10)
bytearray(range(20))
bytearray(b'Hi!')

有類似的類方法fromhex和hex

bytes和bytearray共同的一些類方法

[編輯]
  • count(sub[, start[, end]]):返回不重疊的子串sub的出現次數
  • removeprefix(prefix, /):去除跟定的前綴子串
  • removesuffix(suffix, /)
  • decode(encoding='utf-8', errors='strict'):返回從給定字節解碼的字符串
  • endswith(suffix[, start[, end]])
  • find(sub[, start[, end]]):返回子串sub最小出現的下標值。未找到返回-1
  • index(sub[, start[, end]]):類似find方法,但未找到拋出異常
  • join(iterable):返回一個新的對象
  • maketrans(from, to):這個靜態方法返回一個可用於 bytes.translate() 的轉換表,它將把 from 中的每個字符映射到 to 中相同位置的字符; from 和 to 必須都是類似字節對象(bytes-like objects)並且具有相同的長度。
  • partition(sep):在第一次出現 sep 時拆分序列,並返回一個 3 元組,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之後的部分。 如果未找到分隔符,則返回一個包含原始序列副本的 3 元組,後跟兩個空字節或 bytearray 對象。
  • replace(old, new[, count]):如果給出參數count,只對前面count次替換。
  • rfind(sub[, start[, end]])
  • rindex(sub[, start[, end]])
  • rpartition(sep)
  • startswith(prefix[, start[, end]])
  • translate(table, /, delete=b):返回新對象——刪除了參數 delete 中出現的所有字節,其餘字節通過給定的轉換表映射,該轉換表必須是長度為 256 的字節對象。可以使用 bytes.maketrans() 方法創建轉換表。對於只刪除字符的翻譯,將 table 參數設置為 None。
  • ljust(width[, fillbyte]):返回新對象,在左側填充字符,如果原對象字節長度小於width
  • lstrip([chars]):默認從左側開頭位置刪除空白符。該函數刪除參數chars中所有字符的任意組合;而removeprefix方法只刪除子串。
  • rjust(width[, fillbyte])
  • rsplit(sep=None, maxsplit=- 1)
  • rstrip([chars])
  • split(sep=None, maxsplit=- 1)
  • strip([chars])
  • capitalize()
  • expandtabs(tabsize=8):返回序列的副本,其中所有制表符被指定個數的空格符替換
  • isalnum()
  • isalpha()
  • isascii()
  • isdigit()
  • islower()
  • isspace()
  • istitle()
  • isupper()
  • lower()
  • splitlines(keepends=False):返回一個list
  • swapcase()
  • title()
  • upper()
  • zfill(width):左側零填充

print(格式化參數),轉換說明符包含兩個或多個字符並具有以下組件,這些組件必須按此順序出現:

  1. '%' 字符,標記說明符的開始。
  2. 映射鍵(可選),由帶括號的字符序列組成,為後續字典變量中的key
  3. 轉換標誌(conversion flag,可選),影響某些轉換類型的結果。'#'值轉換使用「alternate form」;'0'表示零填充數值;'-'表示左對齊;' '產生有符號轉換;'+'產生帶正負號的轉換。
  4. 最小字段寬度(可選)。如果指定為「*」(星號),則從值中元組的下一個元素讀取實際寬度,並且要轉換的對象位於最小字段寬度和可選精度之後。
  5. 精度(可選),以「.」形式給出(點)後跟精度。如果指定為 '*'(星號),則從 values 中元組的下一個元素讀取實際精度,並且要轉換的值位於精度之後。
  6. 長度修飾符(可選),可為h, l, L。但Python忽略它們。
  7. 轉換類型。基本類似C語言的sprintf函數。's' 或'b' 表示字節(任何遵循緩衝區協議或具有 __bytes__() 的對象)。'r' 或'a' 表示字節(使用 repr(obj).encode('ascii', 'backslashreplace') 轉換任何 Python 對象)。

例如:

 print(b'%(language)s has %(number)03d quote types.' %{b'language': b"Python", b"number": 2})

array.array

[編輯]

如果需要使用數組,需要如下:

import array
a = array.array('h', [0, 1, 2, 3])

構造函數class array.array(typecode[, initializer])創建一個由 typecode限制類型的新數組,並由initializer的值進行初始化。實際上,會根據initializer的情況調用本類的fromlist()、 frombytes() 或 fromunicode() 方法將初始元素添加到數組中,或者將可迭代對象作為initializer傳給 extend() 方法。

本類的方法或屬性:

  • array.typecode:用於創建數組的類型碼字符。
  • array.itemsize:在內部表示中一個數組項的字節長度。
  • array.append(x):添加一個值為 x 的新項到數組末尾。
  • array.buffer_info():返回一個元組 (address, length) 以給出用於存放數組內容的緩衝區元素的當前內存地址和長度。 以字節表示的內存緩衝區大小可通過 array.buffer_info()[1] * array.itemsize 來計算。
  • array.byteswap():對所有數組項做大小端序交換。 此方法只支持大小為 1, 2, 4 或 8 字節的值;對於其他值類型將引發 RuntimeError。 它適用於從不同字節序機器所生成的文件中讀取數據的情況。
  • array.count(x):返回 x 在數組中的出現次數。
  • array.extend(iterable):將來自 iterable 的項添加到數組末尾。 如果 iterable 是另一個數組,它必須具有 完全 相同的類型碼;否則將引發 TypeError。 如果 iterable 不是一個數組,則它必須為可迭代對象並且其元素必須為可添加到數組的適當類型。
  • array.frombytes(s):添加來自字節串的項,將字符節解讀為機器值的數組(相當於使用 fromfile() 方法從文件中讀取數據)。
  • array.fromfile(f, n):從 file object f 中讀取 n 項並將它們添加到數組末尾。 如果可用數據少於 n 項,則會引發 EOFError,但可用的項仍然會被插入數組。
  • array.fromlist(list):添加來自 list 的項。 這等價於 for x in list: a.append(x),區別在於如果發生類型錯誤,數組將不會被改變。
  • array.fromunicode(s):使用來自給定 Unicode 字符串的數組擴展數組。 數組必須是類型為 'u' 的數組;否則將引發 ValueError。 請使用 array.frombytes(unicodestring.encode(enc)) 來將 Unicode 數據添加到其他類型的數組。
  • array.index(x[, start[, stop]]):返回最小的 i 使得 i 為數組中首次出現的 x 的索引號。 指定可選參數 start 和 stop 以便在數組的一個子部分內部搜索 x。 如果未找到 x 則會引發 ValueError。
  • array.insert(i, x):將值 x 作為新項插入數組的 i 位置之前。 負值將被視為相對於數組末尾的位置。
  • array.pop([i]):從數組中移除序號為 i 的項並將其返回。 可選參數值默認為 -1,因此默認將移除並返回末尾項。
  • array.remove(x):從數組中移除首次出現的 x。
  • array.reverse():反轉數組中各項的順序。
  • array.tobytes():將數組轉換為一個機器值數組並返回其字節表示(即相當與通過 tofile() 方法寫入到文件的字節序列。)
  • array.tofile(f):將所有項(作為機器值)寫入到 file object f。
  • array.tolist():將數組轉換為包含相同項的普通列表。
  • array.tounicode():將數組轉換為一個 Unicode 字符串。 數組必須是類型為 'u' 的數組;否則將引發 ValueError。 請使用 array.tobytes().decode(enc) 來從其他類型的數組生成 Unicode 字符串。

memoryview

[編輯]

memoryview對象支持訪問一個滿足緩衝區協議(buffer protocol)的對象的內部數據而無需複製操作。這包括bytes、bytearray、array.array等類型。如:

a=bytearray([0x10,0x11,0x12,0x13,0x14,0x15,0x16])
v=memoryview(a)

內存視圖轉化為其它類型,可用tobytes、tolist,或者cast方法,或者struct.unpack方法。

len(view)等於tolist的長度

view.ndim = 0則長度為1。view.ndim = 1則長度為view中元素個數。

itemsize特性給出單個元素的字節數。

調用內存視圖的release函數,可以使得原對象實例恢復全部操作能力。

memoryview支持切片和索引操作。

memoryview可修改內容。如:

data = bytearray(b'abcefg')
v = memoryview(data)
v[1:4] = b'123' #data内容变为 bytearray(b'z123fg')

memoryview是按維度和元素值比較相等,如

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

其它方法有:

  • tobytes(order=None):參數值可以為{『C』, 『F』, 『A』}分別表示C語言、Fortran語言、物理序。
  • hex([sep[, bytes_per_sep]]):返回十六進制表示的字符串。
  • tolist()
  • toreadonly():返回只讀的memoryview
  • release():釋放基礎數據。當前memoryview不再有效。
  • cast(format[, shape]):創建一個新的memoryview,但基礎buffer數據不變。如:
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]]]

memoryview的只讀屬性:

  • obj:返回基礎buffer的對象
  • nbytes:總字節數
  • readonly:是否只讀
  • format
  • itemsize
  • ndim:多維數組的維數
  • shape:多維數組的維度的元組表示
  • strides:多維數組各維度的字節步長
  • c_contiguous
  • f_contiguous
  • contiguous

格式說明

[編輯]
格式類型的前綴
字符 字節序 尺寸 對齊
@ native native native
= native standard none
< 小尾序 standard none
> 大尾序 standard none
! 網絡序 standard none
格式類型
Format C Type Python type Standard size 註釋
x pad byte no value
c char bytes of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1 C99引入的類型。返回值是 True或False
h short integer 2
H short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
n ssize_t integer
N size_t integer
e 半精度 float 2
f float float 4
d double float 8
s char[] bytes 整數後跟s,表示字節序列長度。默認為1。會自動截斷或補0位元組
p char[] bytes Pascal string
P void * integer

數字後面跟隨格式字符,表示該格式字符重複的次數。例如:'4h'等價於'hhhh'