字符串編碼
python3和python2的一個(gè)主要差異就在于字符編碼,在python2中聲明的字符串默認(rèn)是bytes
字節(jié)流,而在python3中聲明的字符串默認(rèn)是unicode
字符串,我們用以下代碼進(jìn)行示例:
# if using python2
str_raw = "我們愛(ài)編程"
str_bytes = b"我們愛(ài)編程"
str_unicode = u"我們愛(ài)編程"
print(str_raw) # 輸出 '我們愛(ài)編程'
print(str_bytes) # 輸出 '我們愛(ài)編程'
print(str_unicode) # 輸出 '我們愛(ài)編程'
print(type(str_raw)) # 輸出 <type 'str'>
print(type(str_bytes)) # 輸出 <type 'str'>
print(type(str_unicode)) # 輸出 <type 'unicode'>
# if using python3
str_raw = "我們愛(ài)編程"
str_bytes = b"我們愛(ài)編程" # 會(huì)報(bào)錯(cuò) SyntaxError: bytes can only contain ASCII literal characters.
str_bytes = b"we love programming" # 輸出 b'we love programming'
str_unicode = u"我們愛(ài)編程"
print(str_raw) # 輸出 '我們愛(ài)編程'
print(str_unicode) # 輸出 '我們愛(ài)編程'
print(type(str_raw)) # 輸出 <class 'str'>
print(type(str_unicode)) # 輸出 <class 'str'>
print(type(str_bytes)) # 輸出 <class 'bytes'>
從這個(gè)例子中,我們知道在python2中聲明的字符串默認(rèn)是以bytes
的形式存儲(chǔ)的,如果用交互式終端去打印python2的字符,那么會(huì)顯示如下
>>> str_raw = "我們愛(ài)編程"
>>> str_raw
'\xe6\x88\x91\xe4\xbb\xac\xe7\x88\xb1\xe7\xbc\x96\xe7\xa8\x8b'
而python3中聲明的字符串默認(rèn)以unicode
形式儲(chǔ)存,如果用交互式終端去打印的話,那么顯示如下:
>>> str_raw = "我們愛(ài)編程"
>>> str_raw
'我們愛(ài)編程'
這里需要提一嘴的是,unicode是字符集的編碼,而utf-8是unicode的其中一種編碼實(shí)現(xiàn)(此外還有utf-16等)。然而unicode作為一種能包含100萬(wàn)符號(hào)以上的字符集,其編碼存在一定的冗余,比如嚴(yán)的 Unicode 是十六進(jìn)制數(shù)4E25,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位(100111000100101),不利于數(shù)據(jù)持久化保存和傳輸,因此需要編碼成字節(jié)流bytes進(jìn)行儲(chǔ)存或者網(wǎng)絡(luò)傳輸,關(guān)于字符編碼和字符集的擴(kuò)展知識(shí)可見(jiàn)[1]。如Fig 1.1所示,在python3中稱bytes -> unicode的過(guò)程為解碼,而unicode -> bytes的過(guò)程為編碼,數(shù)據(jù)類(lèi)型而言,在python3中的<class 'str'>其實(shí)對(duì)應(yīng)python2的<type 'unicode'>,python3的<class 'bytes'>對(duì)應(yīng)python2的<type 'str'>。對(duì)于函數(shù)而言,python3的bytes()對(duì)應(yīng)python2的str(),python3的str()對(duì)應(yīng)python2的bytes()。相對(duì)應(yīng)的,對(duì)于python3而言的解碼對(duì)于python2而言是編碼,對(duì)于python3而言的編碼則是python2的解碼。
總而言之,在python中推薦一切字符處理都轉(zhuǎn)換成unicode后進(jìn)行處理,需要持久化或者傳輸時(shí)候在編碼成字節(jié)流進(jìn)行后續(xù)操作。
Fig 1.1 python3中字符串的編碼與解碼。
Reference
[1]. https://zhuanlan.zhihu.com/p/38333902, 字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8