深入淺析python3中的unicode和bytes問(wèn)題
最近寫(xiě)了一些python3程序,四處能看到bytes類(lèi)型,而它并不存在于python2中,這也是python3和python2顯著區(qū)別之一。
以前在寫(xiě)python2代碼的時(shí)候,經(jīng)常會(huì)遇到很多編碼報(bào)錯(cuò)的異常,原因在于python2對(duì)unicode的支持不是特別理想。而在python3中,所有編寫(xiě)的代碼都是unicode,python解析器在運(yùn)行的時(shí)候,內(nèi)部都轉(zhuǎn)換(除非你顯示定義為bytes類(lèi)型)為unicode,減少了出錯(cuò)的可能性。
在python3中,有兩種字符串類(lèi)型,默認(rèn)的就是str,即unicode,也叫做文本類(lèi)型。但一個(gè)程序總是會(huì)有I/O操作(磁盤(pán),網(wǎng)絡(luò)),即I/O二進(jìn)制數(shù)據(jù),在python3中定義為bytes類(lèi)型。bytes類(lèi)型就是一個(gè)個(gè)字節(jié)串,包含0~256 之間的一個(gè)整數(shù)。
那么如何定義bytes類(lèi)型呢,有兩種顯示的方法,比如:
#只能允許ASCII值 x=b'abc' y=b'\xe6\x88\x91' print (x,y) #對(duì)unicode字符集進(jìn)行特定編碼 t=bytes("我們","UTF-8") #輸出b'\xe6\x88\x91\xe4\xbb\xac' #一個(gè)中文字符,UTF-8編碼占用三個(gè)字節(jié) print (t) #返回6,對(duì)于python來(lái)說(shuō),就是字節(jié)序列的長(zhǎng)度 print (len(t)) #返回2,代表兩個(gè)字符 print (len("我們"))
接下去說(shuō)說(shuō)str類(lèi)型和bytes類(lèi)型之間的轉(zhuǎn)換,比如從網(wǎng)絡(luò)上讀取到二進(jìn)制數(shù)據(jù)后,python需要你顯示的將其轉(zhuǎn)換為str類(lèi)型,也就是說(shuō) python不會(huì)隱式在str和bytes之間轉(zhuǎn)換 ,看上去麻煩了很多,但會(huì)減少你出錯(cuò)的幾率,自己明確自己做要的事情。
如果要將str轉(zhuǎn)換為bytes,必須選擇一個(gè)編碼,明確二進(jìn)制數(shù)據(jù)是如何編碼的,比如:
x="我" y=x.encode("UTF-8") z=x.encode("GBK") #b'\xe6\x88\x91' b'\xce\xd2' print (y,z)
如果要將bytes轉(zhuǎn)換為str,也需要一個(gè)編碼,必須說(shuō)明的是,你必須知道 二進(jìn)制數(shù)據(jù)的編碼是什么 ,如果選錯(cuò)了,轉(zhuǎn)換為unicode的時(shí)候會(huì)錯(cuò)誤,另外在python內(nèi)部,它不關(guān)心二進(jìn)制數(shù)據(jù)是什么編碼的,只要是bytes類(lèi)型, 它就是一串字節(jié)序列 ,比如:
x=b'\xe6\x88\x91' print (x.decode("UTF-8")) #會(huì)報(bào)錯(cuò) print (x.decode("GBK"))
總之一句話(huà),“ python內(nèi)部使用unicode,外部使用bytes類(lèi)型 ”,python內(nèi)建庫(kù)中,很多函數(shù)會(huì)說(shuō)明需要str類(lèi)型還是bytes類(lèi)型(嚴(yán)格說(shuō)來(lái)是bytes-like對(duì)象,比如bytes、bytearray ),在寫(xiě)代碼的時(shí)候一定要看清楚,比如 hamc 庫(kù)的new方法,就要求:
hmac.new(key, msg=None, digestmod=None) key is a bytes or bytearray object giving the secret key
很多庫(kù),尤其第三方庫(kù)(比如requests)為了兼容python2和python3,會(huì)在內(nèi)部做很多轉(zhuǎn)換工作,讓你意識(shí)不到bytes類(lèi)型的存在,雖然生產(chǎn)力提高了,但對(duì)于理解python并沒(méi)有太大的好處。
如果要充分理解bytes和str的應(yīng)用,可以參考o(jì)pen和write兩個(gè)內(nèi)建函數(shù)。
使用文本方式打開(kāi)文件,python在內(nèi)部會(huì)自動(dòng)轉(zhuǎn)換為str類(lèi)型,比如:
file ="t.txt" t = open(file,mode="r").read()
而如果是二進(jìn)制方式打開(kāi),如果要顯示在終端,需要轉(zhuǎn)換為str類(lèi)型,比如:
file ="t.txt" t = open(file,mode="rb").read() print (t.decode()) print (t,type(t))
而如果是二進(jìn)制方式寫(xiě)入,則將bytes類(lèi)型數(shù)據(jù)直接寫(xiě)入,比如:
file="t.txt" t=open(file,mode="wb") t.write(b'\xe6\x88\x91')
在上面幾個(gè)例子中,都沒(méi)有說(shuō)明使用那種編碼,如果不顯示指定,一般編碼等同于locale.getpreferedencoding()
。
總結(jié)
以上所述是小編給大家介紹的python3中的unicode和bytes問(wèn)題,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
python中的psutil模塊詳解(cpu、內(nèi)存、磁盤(pán)情況、結(jié)束指定進(jìn)程)
這篇文章主要介紹了python中的psutil(cpu、內(nèi)存、磁盤(pán)情況、結(jié)束指定進(jìn)程),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04python畫(huà)圖系列之個(gè)性化顯示x軸區(qū)段文字的實(shí)例
今天小編就為大家分享一篇python畫(huà)圖系列之個(gè)性化顯示x軸區(qū)段文字的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12使用Pandas實(shí)現(xiàn)可視化帶有標(biāo)簽列的數(shù)據(jù)表
Pandas是Python中一個(gè)靈活強(qiáng)大的數(shù)據(jù)處理庫(kù),它提供了大量數(shù)據(jù)操作和分析工具,本文我們將討論如何使用Pandas可視化帶有標(biāo)簽列的數(shù)據(jù)表,以便更好地呈現(xiàn)和傳達(dá)數(shù)據(jù)的信息,需要的可以了解下2024-02-02Python基礎(chǔ)教程之循環(huán)語(yǔ)句(for、while和嵌套循環(huán))
這篇文章主要給大家介紹了關(guān)于Python基礎(chǔ)教程之循環(huán)語(yǔ)句(for、while和嵌套循環(huán))的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03django之使用celery-把耗時(shí)程序放到celery里面執(zhí)行的方法
今天小編就為大家分享一篇django之使用celery-把耗時(shí)程序放到celery里面執(zhí)行的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07python單向鏈表的基本實(shí)現(xiàn)與使用方法【定義、遍歷、添加、刪除、查找等】
這篇文章主要介紹了python單向鏈表的基本實(shí)現(xiàn)與使用方法,結(jié)合實(shí)例形式分析了Python單向鏈表的定義、遍歷、添加、刪除、查找等相關(guān)操作技巧,需要的朋友可以參考下2019-10-10