日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python高能小技巧:了解bytes与str的区别

發(fā)布時間:2025/3/15 python 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python高能小技巧:了解bytes与str的区别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

導(dǎo)讀:Python有兩種類型可以表示字符序列:一種是bytes,另一種是str。

作者:布雷特·斯拉特金(Brett Slatkin)

來源:大數(shù)據(jù)DT(ID:hzdashuju)

bytes實例包含的是原始數(shù)據(jù),即8位的無符號值(通常按照ASCII編碼標(biāo)準(zhǔn)來顯示)。

a?=?b'h\x65llo' print(list(a)) print(a) >>> [104,?101,?108,?108,?111] b'hello'

str實例包含的是Unicode碼點(code point,也叫作代碼點),這些碼點與人類語言之中的文本字符相對應(yīng)。

a?=?'a\u0300?propos' print(list(a)) print(a) >>> ['a',?'`',?'?',?'p',?'r',?'o',?'p',?'o',?'s'] à?propos

大家一定要記住:str實例不一定非要用某一種固定的方案編碼成二進(jìn)制數(shù)據(jù),bytes實例也不一定非要按照某一種固定的方案解碼成字符串。

  • 要把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)用這些方法的時候,可以明確指出自己要使用的編碼方案,也可以采用系統(tǒng)默認(rèn)的方案,通常是指UTF-8(但有時也不一定,下面就會講到這個問題)。

編寫Python程序的時候,一定要把解碼和編碼操作放在界面最外層來做,讓程序的核心部分可以使用Unicode數(shù)據(jù)來運作,這種辦法通常叫作Unicode三明治(Unicode sandwich)。程序的核心部分,應(yīng)該用str類型來表示Unicode數(shù)據(jù),并且不要鎖定到某種字符編碼上面。

這樣可以讓程序接受許多種文本編碼(例如Latin-1、Shift JIS及Big5),并把它們都轉(zhuǎn)化成Unicode,也能保證輸出的文本信息都是用同一種標(biāo)準(zhǔn)(最好是UTF-8)編碼的。

兩種不同的字符類型與Python中兩種常見的使用情況相對應(yīng):

  • 開發(fā)者需要操作原始的8位值序列,序列里面的這些8位值合起來表示一個應(yīng)該按UTF-8或其他標(biāo)準(zhǔn)編碼的字符串。

  • 開發(fā)者需要操作通用的Unicode字符串,而不是操作某種特定編碼的字符串。

我們通常需要編寫兩個輔助函數(shù)(helper function),以便在這兩種情況之間轉(zhuǎn)換,確保輸入值類型符合開發(fā)者的預(yù)期形式。

第一個輔助函數(shù)接受bytes或str實例,并返回str:

def?to_str(bytes_or_str):if?isinstance(bytes_or_str,?bytes):value?=?bytes_or_str.decode('utf-8')else:value?=?bytes_or_strreturn?value??#?Instance?of?strprint(repr(to_str(b'foo'))) print(repr(to_str('bar'))) >>> 'foo' 'bar'

第二個輔助函數(shù)也接受bytes或str實例,但它返回的是bytes:

def?to_bytes(bytes_or_str):if?isinstance(bytes_or_str,?str):value?=?bytes_or_str.encode('utf-8')else:value?=?bytes_or_strreturn?value??#?Instance?of?bytesprint(repr(to_bytes(b'foo'))) print(repr(to_bytes('bar')))

在Python中使用原始的8位值與Unicode字符串時,有兩個問題要注意。

第一個問題是,bytes與str這兩種類型似乎是以相同的方式工作的,但其實例并不相互兼容,所以在傳遞字符序列的時候必須考慮好其類型。

可以用+操作符將bytes添加到bytes,str也可以這樣。

print(b'one'?+?b'two') print('one'?+?'two') >>> b'onetwo' onetwo

但是不能將str實例添加到bytes實例:

b'one'?+?'two' >>> Traceback?... TypeError:?can't?concat?str?to?bytes

也不能將bytes實例添加到str實例:

'one'?+?b'two' >>> Traceback?... TypeError:?can?only?concatenate?str?(not?"bytes")?to?str

bytes與bytes之間可以用二元操作符(binary operator)來比較大小,str與str之間也可以:

assert?b'red'?>?b'blue' assert?'red'?>?'blue'

但是str實例不能與bytes實例比較:

assert?'red'?>?b'blue'

反過來也一樣,也就是說bytes實例不能與str實例比較:

assert?b'blue'?<?'red'

判斷bytes與str實例是否相等,總是會評估為(False),即便這兩個實例表示的字符完全相同,它們也不相等。例如,在下面這個例子里,它們表示的字符串都相當(dāng)于ASCII編碼之中的foo。

print(b'foo'?==?'foo') >>> False

兩種類型的實例都可以出現(xiàn)在%操作符的右側(cè),用來替換左側(cè)那個格式字符串(format string)里面的%s。

print(b'red?%s'?%?b'blue') print('red?%s'?%?'blue') >>> b'red?blue' red?blue

如果格式字符串是bytes類型,那么不能用str實例來替換其中的%s,因為Python不知道這個str應(yīng)該按照什么方案來編碼。

print(b'red?%s'?%?'blue')

但反過來卻可以,也就是說如果格式字符串是str類型,則可以用bytes實例來替換其中的%s,問題是,這可能跟你想要的結(jié)果不一樣。

print('red?%s'?%?b'blue') >>> red?b'blue'

這樣做,會讓系統(tǒng)在bytes實例上面調(diào)用__repr__方法,然后用這次調(diào)用所得到的結(jié)果替換格式字符串里的%s,因此程序會直接輸出b'blue',而不是像你想的那樣,輸出blue本身。

第二個問題發(fā)生在操作文件句柄的時候,這里的句柄指由內(nèi)置的open函數(shù)返回的句柄。這樣的句柄默認(rèn)需要使用Unicode字符串操作,而不能采用原始的bytes。習(xí)慣了Python 2的開發(fā)者,尤其容易碰到這個問題,進(jìn)而導(dǎo)致程序出現(xiàn)奇怪的錯誤。例如,向文件寫入二進(jìn)制數(shù)據(jù)的時候,下面這種寫法其實是錯誤的。

with?open('data.bin',?'w')?as?f:f.write(b'\xf1\xf2\xf3\xf4\xf5') >>> Traceback?... TypeError:?write()?argument?must?be?str,?not?bytes

程序發(fā)生異常是因為在調(diào)用open函數(shù)時,指定的是'w'模式,所以系統(tǒng)要求必須以文本模式寫入。如果想用二進(jìn)制模式,那應(yīng)該指定'wb'才對。在文本模式下,write方法接受的是包含Unicode數(shù)據(jù)的str實例,不是包含二進(jìn)制數(shù)據(jù)的bytes實例。所以,我們得把模式改成'wb'來解決該問題。

with?open('data.bin',?'wb')?as?f:f.write(b'\xf1\xf2\xf3\xf4\xf5')

讀取文件的時候也有類似的問題。例如,如果要把剛才寫入的二進(jìn)制文件讀出來,那么不能用下面這種寫法。

with?open('data.bin',?'r')?as?f:data?=?f.read()

程序出錯,是因為在調(diào)用open函數(shù)時指定的是'r'模式,所以系統(tǒng)要求必須以文本模式來讀取。若要用二進(jìn)制格式讀取,應(yīng)該指定'rb'。以文本模式操縱句柄時,系統(tǒng)會采用默認(rèn)的文本編碼方案處理二進(jìn)制數(shù)據(jù)。

所以,上面那種寫法會讓系統(tǒng)通過bytes.decode把這份數(shù)據(jù)解碼成str字符串,再用str.encode把字符串編碼成二進(jìn)制值。然而對于大多數(shù)系統(tǒng)來說,默認(rèn)的文本編碼方案是UTF-8,所以系統(tǒng)很可能會把b'\xf1\xf2\xf3\xf4\xf5'當(dāng)成UTF-8格式的字符串去解碼,于是就會出現(xiàn)上面那樣的錯誤。為了修正錯誤,需要把模式改成'rb'。

with?open('data.bin',?'rb')?as?f:data?=?f.read()assert?data?==?b'\xf1\xf2\xf3\xf4\xf5'

另一種改法是在調(diào)用open函數(shù)的時候,通過encoding參數(shù)明確指定編碼標(biāo)準(zhǔn),以確保平臺特有的一些行為不會干擾代碼的運行效果。例如,假設(shè)剛才寫到文件里的那些二進(jìn)制數(shù)據(jù)表示的是一個采用'cp1252'標(biāo)準(zhǔn)(cp1252是一種老式的Windows編碼方案)來編碼的字符串,則可以這樣寫:

with?open('data.bin',?'r',?encoding='cp1252')?as?f:data?=?f.read()assert?data?==?'?òó??'

這樣程序就不會出現(xiàn)異常了,但返回的字符串也與讀取原始字節(jié)數(shù)據(jù)所返回的有很大區(qū)別。通過這個例子,我們要提醒自己注意當(dāng)前操作系統(tǒng)默認(rèn)的編碼標(biāo)準(zhǔn)(可以執(zhí)行 python3 -c 'import locale; print(locale.getpreferredencoding())'命令查看),了解它與你所期望的是否一致。如果不確定,那就在調(diào)用open時明確指定encoding參數(shù)。

要點

  • bytes包含的是由8位值所組成的序列,str包含的是由Unicode碼點所組成的序列。

  • 我們可以編寫輔助函數(shù)來確保程序收到的字符序列確實是期望要操作的類型(要知道自己想操作的到底是Unicode碼點,還是原始的8位值。用UTF-8標(biāo)準(zhǔn)給字符串編碼,得到的就是這樣的一系列8位值)。

  • bytes與str這兩種實例不能在某些操作符(例如>、==、+、%操作符)上面混用。

  • 從文件中讀取二進(jìn)制數(shù)據(jù)(或者把二進(jìn)制數(shù)據(jù)寫入文件)時,應(yīng)該用'rb'('wb')這樣的二進(jìn)制模式打開文件。

  • 如果要從文件中讀取(或者要寫入文件之中)的是Unicode數(shù)據(jù),那么必須注意系統(tǒng)默認(rèn)的文本編碼方案。若無法肯定,可通過encoding參數(shù)明確指定。

關(guān)于作者:布雷特·斯拉特金(Brett Slatkin),Google首席軟件工程師,他是Google Surveys的聯(lián)合技術(shù)創(chuàng)始人,也是PubSubHubbub協(xié)議的共同創(chuàng)造者之一。此外,Slatkin還發(fā)布了Google的第一個云計算產(chǎn)品——App Engine。早在15年前,Slatkin就開始在工作中使用Python管理Google大量的服務(wù)器群。他擁有紐約哥倫比亞大學(xué)計算機(jī)工程專業(yè)學(xué)士學(xué)位。

本文摘編自《Effective Python:編寫高質(zhì)量Python代碼的90個有效方法》(原書第2版),經(jīng)出版方授權(quán)發(fā)布。

延伸閱讀《Effective Python》(原書第2版)

點擊上圖了解及購買

轉(zhuǎn)載請聯(lián)系微信:DoctorData

推薦語:Python編程進(jìn)階必讀,基于Python3.8,新增31條建議!掌握Pythonic編程方式,寫出高質(zhì)量代碼|進(jìn)階到編程高手的程序員修煉之道和代碼整潔之道。

劃重點????

干貨直達(dá)????

  • 詳解4種類型的爬蟲技術(shù)

  • 3段極簡代碼帶你入門Python科學(xué)計算庫SciPy

  • 眼花繚亂的數(shù)據(jù)庫,怎樣選擇?給你這個書單,想學(xué)哪個學(xué)哪個

  • 學(xué)習(xí)數(shù)據(jù)分析,有哪些好書值得讀?都在這里了

更多精彩????

在公眾號對話框輸入以下關(guān)鍵詞

查看更多優(yōu)質(zhì)內(nèi)容!

PPT?|?讀書?|?書單?|?硬核?|?干貨?|?講明白?|?神操作

大數(shù)據(jù)?|?云計算?|?數(shù)據(jù)庫?|?Python?|?可視化

AI?|?人工智能?|?機(jī)器學(xué)習(xí)?|?深度學(xué)習(xí)?|?NLP

5G?|?中臺?|?用戶畫像?|?1024?|?數(shù)學(xué)?|?算法?|?數(shù)字孿生

據(jù)統(tǒng)計,99%的大咖都關(guān)注了這個公眾號

????

新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

總結(jié)

以上是生活随笔為你收集整理的Python高能小技巧:了解bytes与str的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本一本久草 | 伊人五月综合 | 女优一区二区三区 | 日韩一级视频在线观看 | 好吊一区二区三区视频 | 韩国日本美国免费毛片 | 中文字幕一区二区三区视频 | 操女人逼逼视频 | 在线观看一区视频 | 国产在线黄 | 黑人性视频 | 图片区亚洲色图 | 综合性色 | 亚洲国产精品无码观看久久 | 人人91 | 日本老妇高潮乱hd | 青青操在线视频 | 国产一区二区三区网站 | 久久99国产精品 | www天堂网| 欧美日韩二区三区 | 精品久久久久久无码中文野结衣 | 午夜少妇久久久久久久久 | 性爱免费视频 | 懂色av蜜臂av粉嫩av | v在线| 欧美人人爽 | 涩涩成人网 | 99久久综合| 久久精品www人人爽人人 | 成人在线观看小视频 | 波多野结衣国产 | 中文字幕av网址 | 五月婷婷丁香花 | 两口子交换真实刺激高潮 | 男人久久久 | 自拍偷拍亚洲综合 | 久久久精品人妻av一区二区三区 | 五月天啪啪| 67194国产| 成人av无码一区二区三区 | 天天干导航 | 卡一卡二在线视频 | 国产精品久久久免费 | 欧美午夜精品一区 | 国产一区二区女内射 | 丰满人妻一区二区三区免费视频棣 | 天堂网av手机版 | 国产做爰视频免费播放 | 精品视频一区二区在线观看 | 亚洲va国产天堂va久久 en | 日本三级韩国三级三级a级中文 | 国产对白羞辱绿帽vk | 国产日韩在线播放 | 欧美视频在线一区二区三区 | 国产欧美成人 | 免费av在线网址 | av网站有哪些 | 欧美高清性xxxxhd | 狠狠精品干练久久久无码中文字幕 | 91av免费观看 | 亚洲无线视频 | 720url在线观看免费版 | 黄色a∨ | 国产又黄又嫩又滑又白 | 国产不卡免费视频 | 亚洲春色在线观看 | 国产亚洲精品久久777777 | 久久大胆视频 | 一二三四区在线 | 国产欧美一区二区三区另类精品 | 国产精品呦呦 | 人人插人人搞 | 精品久久久99 | 午夜羞羞影院 | 欧美激情欧美激情在线五月 | 国产专区自拍 | 亚洲永久在线 | av成人在线网站 | 四虎免费观看 | 2025国产精品 | 国产主播一区二区 | 久久久久久久中文字幕 | 五月综合久久 | 蜜桃va| 久久中文字幕精品 | 99av国产精品欲麻豆 | 噜噜噜精品欧美成人 | 黄色av免费播放 | 欧美日韩影院 | 激情插插| 亚洲在线色 | 天天摸夜夜添 | 91网在线播放 | 欧美一级二级片 | 欧美特级黄 | 天天干夜夜欢 | 色综合天天干 | 国产精品国语自产拍在线观看 |