PyTips 0x08 - Python 字節與字節數組

項目地址:https://git.io/pytipshtml

0x07 中介紹了 Python 中的字符串類型,字符串類型是對人類友好的符號,但計算機只認識一種符號,那就是二進制(binary)數,或者說是數字:python

OpenCV

上面這張圖片來自 OpenCV,很是直觀地解釋了計算機處理的信息與咱們看到的圖像之間的關係。回到 Python 對字節和字節數組的定義:git

The core built-in types for manipulating binary data are bytes and bytearray.github

1Byte of ASCII

爲了用計算機能夠理解的數字描述人類使用的字符,咱們須要一張數字與字符對應的表。咱們都知道在計算機中 1 byte = 8bits,能夠存儲 0~255 共256個值,也就是說 1byte 最多能夠表示 256 個字符,在最初的計算機世界中,256 足以容納全部大小寫英文字母和 0~9 阿拉伯數字以及一些經常使用的符號,因而就有了 ASCII 編碼:數組

ascii

在 Python 中建立字節與字符串相似,只不過須要在引號外面加一個前綴bui

print(b"Python")
python = (b'P' b'y' b"t" b'o' b'n')
print(python)
b'Python'
b'Pyton'

Bytes 表明的是(二進制)數字的序列,只不過在是經過 ASCII 編碼以後纔是咱們看到的字符形式,若是咱們單獨取出一個字節,它仍然是一個數字:編碼

print(b"Python"[0])
80

咱們能夠用 b"*" 的形式建立一個字節類型,前提條件是這裏的 * 必須是 ASCII 中可用的字符,不然將會超出限制:spa

print(b"雨")
File "<ipython-input-3-1f95d71c6553>", line 1
    print(b"雨")
         ^
SyntaxError: bytes can only contain ASCII literal characters.

錯誤提示說明:字節類型只能容許 ASCII 字符。3d

0~127~255code

那麼問題來了,咱們發現上面的 ASCII 表裏面全部的字符只佔據了 [31, 127],那對於這一範圍以外的數字咱們要怎麼才能表示爲字節類型?答案就是用特殊的轉義符號\x+十六進制數字 :

print(b'\xff'[0])
print(b'\x24')
255
b'$'

反過來咱們也能夠將數字(0~255)轉變成轉義後的字節類型:

print(bytes([24]))
print(bytes([36,36,36])) # 記住字節類型是一個序列
b'\x18'
b'$$$'

或者直接從十六進制得來:

print(bytes.fromhex("7b 7d"))

# 逆運算
print(b'{ }'.hex())

int(b' '.hex(), base=16)
b'{}'
7b207d
32

encode

字符串有 decode 方法,而字節有 encode 方法,咱們這裏先簡單看一下 encode('ascii') 。對於給定的字符咱們能夠經過編碼獲得它在編碼表裏面的座標(即碼位),所以對字符進行encode('ascii')操做是找到其在 ASCII 中的位置:

print("$".encode('ascii'))
print("$".encode('ascii')[0])
b'$'
36

也就是說字符 "$"0x07中已經介紹過這是一個 Unicode 編碼的字符)在 ASCII 中的位置就是 $(或者說36)。

但是若是咱們對一些奇怪的字符進行 ASCII 編碼,就會發生:

snake = '?'
try:
    snake.encode('ascii')
except UnicodeEncodeError as err:
    print(err)

# 正確的作法應該是用 UTF-8 進行編碼,由於字符串都是 UTF-8 的
print(snake.encode()) # utf-8 by default
'ascii' codec can't encode character '\U0001f40d' in position 0: ordinal not in range(128)
b'\xf0\x9f\x90\x8d'

因而就獲得了咱們最熟悉的錯誤:ordinal not in range(128),至於爲何是 128,如今應該很好理解了吧!

字節數組

和字符串同樣,字節類型也是不可變序列,而字節數組就是可變版本的字節,它們的關係就至關於listtuple

ba = bytearray(b'hello')
ba[0:1] = b'w'
print(ba)
bytearray(b'wello')

因爲和字符串同樣是序列類型,字節和字節數組可用的方法也相似,這裏就不一一列舉了。

總結

  1. 字節(字節數組)是二進制數據組成的序列,其中每一個元素由8bit二進制即1byte亦即2位十六進制數亦亦即0~255組成;

  2. 字節是計算機的語言,字符串是人類語言,它們之間經過編碼表造成一一對應的關係;

  3. 最小的 ASCII 編碼表只須要一位字節,且只佔用了其中 [31,127] 的碼位;

關於字節與字符串之間的關係,將在下一期[0x08]()詳細介紹。

參考

  1. Pragmatic Unicode


歡迎關注公衆號 PyHub!

歡迎關注公衆號 PyHub!

相關文章
相關標籤/搜索