python數據類型bytes 和 bytearray的使用與區別
bytes 和 bytearray
bytes 和 bytearray 都是二進制世界的成員,用二進制的方式去理解才能看清他的本質。
理解bytes 和 bytearray
0 和 1 是計算機工作的根本,單個的0和1隻能表達兩種狀態,無法滿足我們復雜的計算,於是計算機使用瞭8位即一個byte作為一個儲存的基本單位。
byte 由 8bit 組成,例如 0000 0001 , 也可以表示為16進制的形式:0x01, 0x為固定前綴,表示該數使用16進制表示方式,此外0o前綴為8進制,0b為二進制形式,以此區分。bytes 從字面上理解是byte 的復數, 也就是多個byte組成的序列。這一點與字符串與字符的關系類似。
於是,我們可以這樣理解,字符串是由一個個字符順序儲存組成的序列,其中每個元素為一個字符。bytes 是由一個個byte組成的序列,每一個元素是一個byte。
bytearray是一個由byte為元素組成的array,其中每一個元素為一個byte。在python官方文檔中,作者簡單的定義瞭這兩個類型。翻譯為
bytes:可以看作是一組二進制數值(0-255) 的 str 序列bytearray :可以看作是一組二進制數值(0-255) 的 list 序列
python中值的表示
在計算機中表示數有多種表示方式,普通的表示方式就是10進制的數值表示方法,例如a=10,此外還有8進制,16進制,2進制的表示方式,分別使用前綴0o和0x和0b表示。
a = 97 a = 0b01100001 a = 0x61 a = 0o301
使用上面4種方式定義的值均為十進制數97,也就是上面四種方式是等價得,隻是使用不同的進制表示同一個值。
除瞭使用數值可以有不同的表示方式外,還可以使用字節的方式來定義一個值,而字節該如何書寫?python使用瞭一個特殊字符串來表示字節,這個特殊字符可以使用前綴\x,\o, \b和\ 表示,分別表示16,8,2,10進制的表示方式,特殊字符後是對應的進制表示值。示例
a = "a" a = "\b01100001" a = "\x61" a = "\o301"
同樣得,這樣得四種方式是等價得,a變量的值均為"a"。以上是單字節的字符的表示,多字節字符或者是一個字符串同樣可以如此定義。
# 使用encode查看一下中國的二進制編碼為 str.encode("中國") # ==> b'\xe4\xb8\xad\xe5\x9b\xbd',前綴 b表示該值的類型為bytes,區別於字符串的表示 # 因此,我們可以使用這個字節表示來定義“中國” a = '\xe4b8ade59bbd' # 或者 '\xe4\xb8\xad\xe5\x9b\xbd',兩種方式均可 # 其8進制可以如此計算 num = int.from_bytes(a, "big") # 將這段字符串轉化為內存等值的數值 print(oct(num)) # 打印該數值的8進制表示,結果為字符串類型。在該字符串加上\o前綴即可 # 最後打印結果 print(a) # ==> "中國" # 再假如我們需要定義一個字符串abc,可以使用下面的方式 a = "abc" a = "\x616263" # 由於abc的ascii碼分別為 0x61 62 63 a = "\o301302303" # 由於abc的ascii碼分別為 0o301 302 303 a = "\979899" # 由於abc的ascii碼分別為 979899
進制轉換
字節,數值,字符等類型可以使用下面的方式進行轉化。還包括值得不同進制表示,字符串得不同進制表示,示例:
# 內置函數 chr(97) # ==> "a" ord("a") # ==> 97 # 將一個10進制數,轉化為其他進制的數的字符串表示得內置函數,註意,結果都是字符串,而不是對應進制的數值 bin(97) # ==> '0x61' oct(97) # 8進制字符 '0o301' hex(97) # 2進制字符 '0b01100001' # 也可使用format完成 #帶前綴 0x format(97,"#x") # ==> '0x61' format(97,"#o") # 8進制字符 '0o301' format(97,"#b") # 2進制字符 '0b01100001' #不帶前綴 format(97,"X") # ==> '61' format(97,"o") # ==> '301' format(97,"b") # ==> '01100001' # 3.6+版本使用方法 # f'{255:X}' 和 f'{255:#X}' ===> " FF " 和 "0xFF" # 使用c 風格得表示 "%x"%10 # ==> 'a' "%o"%10 # ==> '12' # 帶前綴 "%#x"%10 # ==> '0xa' "%#o"%10 # ==> '0o12'
將一個字節或者字符或者字符串轉化為值類型可以使用如下的方式。
ord("a") # ==> 97 int.from_bytes(b"a", "big") # 97 類型為int,指定大端模式(小地址存多字節高位) # 以下兩種形式等價 int.from_bytes(b"abc", "big") # ==> 得到三字節長度的數值 int.from_bytes(bytes("abc"), "big") #
bytes類型
將一個str 轉化為 bytes 的本質是將str中的每個字符轉化為該字符的二進制編碼形式。例如 a 的二進制為 0x65。
# 將字符串abc 中每一個字符轉化為二進制編碼形式就是bytes類型 s = "abc" bs1 = bytes("abc") # bytes()第一個參數為一個可迭代對象,將每一個元素轉為二進制的表示方式 print(s) # 'abc' print(bs1) # b'abc' python檢測到這個二進制序列可以使用字符abc表示,但是為瞭區別於abc的字符串,所以使用 b'abc',隻是給人看的一種表示結果。實際的值應該是一個個字節。 # 我們看一下單個元素 print(s[0]) # 'a' print(bs1[0]) # 97 而不是 b'a',對於單個字節0x61, python使用瞭十進制數97表示
二進制類型bytes使用b'abc'的表示方式,隻是嘗試將這個序列中的元素翻譯為人類可以看懂的形式,實際在變量內存中儲存的為一個個二進制字節0x61 0x62 0x63,這樣的三個字節可以根據數據類型的不同翻譯成不同的結果。
b2 = bytes( [97,98,99] ) print(b2) # ==> b'abc'
這就對上面結論最佳證明,出現該結果的原因是,python中的列表 [97, 98, 99] 在內存中二進制儲存和字符串abc儲存的值是相同的,所以使用python來展示這段內存時,它使用b'abc'的方式進行展示。
bytes類型轉化
字符串轉bytes類型
# 將返回 bytes 類型 b" abc ", 可以添加encoding參數指定字符串的編碼方式 bs1 = bytes("abc","utf-8") # 可以使用字符的16進制字符表達形式 bs2 = bytes('\x61\x62\x63',"utf-8") # 直接對字符進行編碼成二進制形式 bs2 = "abc".encode() # 16進制字符轉為bytes類型 b1 = bytes.fromhex("61 62 63") # ==> b"abc" "61,62"是兩個16進制數組合,單個值不能超過 7F也就是不能超過127 ,否則無法對應ASCII表中的字符 b1.hex() # ===> '616263' ASCII碼中abc字符對應的16進制數組成的字符串,上面函數的逆運算。
數值轉化為bytes類型
想要使用數值來定義一個不能直接使用 bytes(97) 的方式來定義,這不會在內存中儲存一個二進制的 97,而是會開辟97個字節,每個字節的值為0x00。這是需要註意的一點,如果想要儲存一個97,可以使用列表來實現。
# 傳入數值類型可迭代對象 b1 = bytes(range(97,100)) # ==> b'abc' b2 = bytes([97,98,99]) # ==> b'abc' b3 = bytes([97]) # ==> b'a' # 直接傳入10進制數值對象而不是可迭代對象,將會生成對應數值字節的空bytes b4 = bytes(3) # b'\x00\x00\x00' 三個空字符的 bytes # 通過數值轉化將8進制,16進制數字 生成bytes對象 b5 = bytes([int("61",16)]) #16進制61 == > 10 進制 ==> bytes ==> b"a" (使用字符a表示) b6 = bytes([int("61", 8)]) # 8進制61 == > 10 進制 ==> bytes ==> b"1" (使用字符1表示) # 也可利用bytes 對象轉化為 10 進制 數值 num = int.from_bytes(b"abc","big") # "abc"對應的三個字節拼接在一起作為一個二進制數,並計算為10進制數輸出 print(num) # ===> 6382179
以上是將數值和字符串轉化為 字節類型,這是常用的類型轉化方式,同樣的,也可以將字節轉化為字符或者值的類型。使用以下的方法即可
bytes轉數值
bytes類型轉化為 值類型使用 數值使用 int的一個類方法from_bytes即可,示例:
num = int.from_bytes(b“abc”, "big") # 將這個bytes對象轉化為內存等值的數值
bytes的方法
bytes對象的方法和字符串的方法基本一致,可以進行字符串的幾乎所有操作,例如字符串的replace,split,partation等操作,唯一需要區別的是。字符串的操作操作的對象是一個字符串或者單個字符,而bytes對象操作的是一個bytes二進制字節,例如進行字符串替換時:
"abc".replace("a", "x") # 將字符a 替換為 x # 而在bytes對象 b"abc".replace(b"a", b"x") # 無論是參數中的對象還是對象本身都是bytes類型,有b“”前綴標識
其他方法類比於str的方法,並結合官方文檔即可。
bytearray
bytearray類似於中的list數據類型,bytearray中的每一個元素始終為一個字節值,也就是 0x00 – 0xff 區間的一個值,如果不在該范圍內的值,在指定瞭編碼方式的情況下可以按照字節遍歷
初始化一個bytearray對象。同樣需要一個可迭代對象作為參數,將會按照字節遍歷整個可迭代對象,有以下的方式
bytearray("abc", encoding="utf-8") # abc字符串使用utf-8的方式編碼為字節,每個字節作為bytearray對象的一個元素儲存即可。 bytearray(b"abc") # 也可以使用bytes 類型,而使用bytes類型就沒有編碼一說瞭 bytearray([97, 98, 99]) # 使用可迭代對象,內部元素為一個一個0-255的數值類型。 ba1 = bytearray(range(97,103)) # 可迭代當然包括range對象
ba1 # bytearay對象,==> bytearray(b"abcdef") ba1[0] # ==> 97 (integer) ba1[1:4] # 切片 ==> bytearray(b'bcd') # 賦值,可變 bytearray ba[ 4 ] = 122 # 122整型對應字符"z", ==> b"e" --> b"z" ba # bytearray(b"abcdzf" ) ba1[1:4] = b"xyz" # 切片賦值,替換ba1[1:4]的內容, 隻有bytes 或bytearray 序列可賦值
bytes和bytearray類型之間可以直接進行轉化,bytes()中可以傳入一個bytearray對象作為參數,並且不存在編碼問題,因為兩個類型都是一個二進制的序列。
python在展示bytearray對象,使用的是bytesarray(b"abc") 的方式,其實,不妨理解為 bytearray( [ b"a", b"b", b"c" ] ) 的形式。也就是每個元素為字節列表。所以byteaarray實現瞭和列表對象的方法,並且可以進行元素的替換,也就是與列表相同,他是一個可變類型的對象。而bytes 與字符串都是不可變的,無法對單個元素進行替換,對象一旦產生將不可變。如果需要改變,需要新建一個新的對象。
bytearray的方法
類似與 列表對象,可以進行切片,append, extend,insert等操作,同樣的,由於內部的元素都是一個個字節對象,對單個元素操作時隻能操作單字節的對象,而執行extend這類處理可迭代對象方法,也要求可迭代對象內部的所有元素為單字節對象。單字節對象,可以是 b"a"類似的單字節對象 或 0-255的數值。因為一個字節隻能儲存256中狀態。以下是幾個簡單的示例
a = bytearray(b"abc") a.append(100) print(a) # bytearray(b"abcd") a.append(b"e") print(a) # bytearray(b"abcde") a.extend(a) print(a) # bytearray(b"abcdeabcde") a.insert(0, b"A") print(a) # bytearray(b"Aabcdeabcde") bytes(a) # b"Aabcdeabcde"
到此這篇關於python數據類型bytes 和 bytearray的使用與區別的文章就介紹到這瞭,更多相關python bytes 和 bytearray內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Python語言中的數據類型-序列
- python快速入門題目詳解
- Python字符串編碼轉換 encode()和decode()方法詳細說明
- python字符串常規操作大全
- 關於python基礎數據類型bytes進制轉換