Effective Python bytes 與 str 的區(qū)別
1、Python 有兩種類型可以表示字符序列
bytes
:實(shí)例包含的是 原始數(shù)據(jù) ,即 8 位的無(wú)符號(hào)值(通常按照 ASCII 編碼 標(biāo)準(zhǔn)來(lái)顯示)str
:實(shí)例包含的是Unicode
碼點(diǎn)(code point,也叫作代碼點(diǎn)),這些碼點(diǎn)與人類語(yǔ)言之中的文本字符相對(duì)應(yīng)
a = b'h\x6511o' print(list(a)) print(a) a = 'a\\u300 propos' print(list(a)) print(a) # 輸出結(jié)果 [104, 101, 49, 49, 111] b'he11o' ['a', '\\', 'u', '3', '0', '0', ' ', 'p', 'r', 'o', 'p', 'o', 's'] a\u300 propos
2、Unicode 數(shù)據(jù)和二進(jìn)制數(shù)據(jù)轉(zhuǎn)換
- 把
Unicode
數(shù)據(jù)轉(zhuǎn)換成二進(jìn)制數(shù)據(jù),必須調(diào)用 str 的encode
方法(編碼) - 把二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成
Unicode
數(shù)據(jù),必須調(diào)用 bytes 的decode
方法(解碼) - 調(diào)用這些方法時(shí),可以明確指出字符集編碼,也可以采用系統(tǒng)默認(rèn)的方案,通常是 UTF-8
3、使用原始的 8 位值與 Unicode 字符串
使用原始的 8 位值與 Unicode 字符串時(shí)需要注意的兩個(gè)問(wèn)題:
- 該問(wèn)題等價(jià)于:使用
bytes
和str
時(shí)需要注意的兩個(gè)問(wèn)題
3.1 問(wèn)題一:bytes 和 str 的實(shí)例互不兼容
使用 + 操作符:
# bytes+bytes print(b'a' + b'1') # str+str print('b' + '2') # 輸出結(jié)果 b'a1' b2
bytes + bytes
,str + str
都是允許的- 但
bytes + str
會(huì)報(bào)錯(cuò)
#
bytes+str print('c' + b'2') # 輸出結(jié)果 print('c' + b'2') TypeError: can only concatenate str (not "bytes") to str
同類型之間也可以用二元操作符來(lái)比較大小
assert b'c' > b'a' assert 'c' > 'a'
但 bytes
和 str
之間用二元操作符也會(huì)報(bào)錯(cuò)
assert b'c' > 'a' # 輸出結(jié)果 assert b'c' > 'a' TypeError: '>' not supported between instances of 'bytes' and 'str'
判斷 bytes
與 str
實(shí)例是否相等
兩個(gè)類型的實(shí)例相比較總會(huì)為 False
,即使字符完全相同
# 判斷 str、bytes print('a' == b'a') # 輸出結(jié)果 False
格式化字符串中的 %s
兩種類型的實(shí)例都可以出現(xiàn)在 %
操作符的右側(cè),用來(lái)替換左側(cè)那個(gè)格式字符串(format string
)里面的 %s
但是!如果格式字符串是 bytes
類型,那么 不能 用 str
實(shí)例來(lái)替換其中的 %s
,因?yàn)?Python
不知道這個(gè) str
應(yīng)該按照什么字符集來(lái)編碼
# % print(b'red %s' % 'blue') # 輸出結(jié)果 print(b'red %s' % 'blue') TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'
但是!反過(guò)來(lái)卻可以,如果格式字符串是 str 類型,則 可以 用bytes
實(shí)例來(lái)替換其中的 %s
,但結(jié)果可能不是預(yù)期結(jié)果
# % print('red %s' % b'blue') # 輸出結(jié)果 red b'blue'
這樣會(huì)讓系統(tǒng)在 bytes
實(shí)例上面調(diào)用 __repr__
方法
調(diào)用結(jié)果替換格式字符串里的 %s,因此程序會(huì)直接輸出 b'blue'
,而不是輸出 blue
3.2問(wèn)題二:操作文件句柄時(shí)需要使用 Unicode 字符串操作
不能使用原始的 bytes
向文件寫入二進(jìn)制數(shù)據(jù)會(huì)報(bào)錯(cuò):
# 寫入二進(jìn)制數(shù)據(jù) with open('test.txt', "w+") as f: f.write(b"\xf1\xf2") # 輸出結(jié)果 f.write(b"\xf1\xf2") TypeError: write() argument must be str, not bytes
- 報(bào)錯(cuò)是因?yàn)?code> w 模式必須以 文本 模式寫入
- 將模式改成
wb
即可正常寫入二進(jìn)制數(shù)據(jù)
with open('test.txt', "wb") as f: f.write(b"\xf1\xf2") 讀取文件中二進(jìn)制數(shù)據(jù) with open('test.txt', "r+") as f: f.read() # 輸出結(jié)果 (result, consumed) = self._buffer_decode(data, self.errors, final) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte
- 報(bào)錯(cuò)是因?yàn)?r 模式必須以 文本 模式讀取
- 以文本模式操縱文件句柄時(shí),系統(tǒng)會(huì)采用 默認(rèn)的文本編碼 方案處理二進(jìn)制數(shù)據(jù)
- 所以,上面那種寫法會(huì)讓系統(tǒng)通過(guò)
bytes.decode
把這份數(shù)據(jù)解碼成 str 字符串,再用str.encode
把字符串編碼成二進(jìn)制值 - 然而對(duì)于大多數(shù)系統(tǒng)來(lái)說(shuō),默認(rèn)的文本編碼方案是
UTF-8
,所以系統(tǒng)很可能會(huì)把b'\xf1\xf2\xf3\xf4\xf5'
當(dāng)成 UTF-8 格式的字符串去解碼,于是就會(huì)出現(xiàn)上面那樣的錯(cuò)誤
將模式改成 rb 即可正常讀取二進(jìn)制數(shù)據(jù):
with open('test.txt', "rb") as f: print(b"\xf1\xf2" == f.read()) # 輸出結(jié)果 True
另一種改法,設(shè)置 encoding 參數(shù)指定字符串編碼:
with open('test.txt', "r", encoding="cp1252") as f: print(f.read()) # 輸出結(jié)果 ñò
這樣也不會(huì)有異常了
需要注意:當(dāng)前操作系統(tǒng)默認(rèn)的字符集編碼,Python 一行代碼查看當(dāng)前操作系統(tǒng)默認(rèn)的編碼標(biāo)準(zhǔn)
在 cmd 中執(zhí)行:
> python3 -c 'import locale; print(locale.getpreferredencoding())' UTF-8
到此這篇關(guān)于Effective Python bytes 與 str 的區(qū)別的文章就介紹到這了,更多相關(guān)Python bytes 與 str 的區(qū)別內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。