久久精品国产亚洲高清|精品日韩中文乱码在线|亚洲va中文字幕无码久|伊人久久综合狼伊人久久|亚洲不卡av不卡一区二区|精品久久久久久久蜜臀AV|国产精品19久久久久久不卡|国产男女猛烈视频在线观看麻豆

    1. <style id="76ofp"></style>

      <style id="76ofp"></style>
      <rt id="76ofp"></rt>
      <form id="76ofp"><optgroup id="76ofp"></optgroup></form>
      1. 千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機構(gòu)

        手機站
        千鋒教育

        千鋒學(xué)習(xí)站 | 隨時隨地免費學(xué)

        千鋒教育

        掃一掃進入千鋒手機站

        領(lǐng)取全套視頻
        千鋒教育

        關(guān)注千鋒學(xué)習(xí)站小程序
        隨時隨地免費學(xué)習(xí)課程

        當前位置:首頁  >  技術(shù)干貨  > 如何理解Python中bytes與str的區(qū)別

        如何理解Python中bytes與str的區(qū)別

        來源:千鋒教育
        發(fā)布人:xqq
        時間: 2023-11-05 21:50:38 1699192238

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

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

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

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

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

        要把Unicode數(shù)據(jù)轉(zhuǎn)換成二進制數(shù)據(jù),必須調(diào)用str的encode方法。

        要把二進制數(shù)據(jù)轉(zhuǎn)換成Unicode數(shù)據(jù),必須調(diào)用bytes的decode方法。

        調(diào)用這些方法的時候,可以明確指出自己要使用的編碼方案,也可以采用系統(tǒng)默認的方案,通常是指UTF-8(但有時也不一定,下面就會講到這個問題)。

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

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

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

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

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

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

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

        defto_str(bytes_or_str):ifisinstance(bytes_or_str,bytes):value=bytes_or_str.decode('utf-8')else:value=bytes_or_strreturnvalue#Instanceofstrprint(repr(to_str(b'foo')))print(repr(to_str('bar')))>>>'foo''bar'

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

        defto_bytes(bytes_or_str):ifisinstance(bytes_or_str,str):value=bytes_or_str.encode('utf-8')else:value=bytes_or_strreturnvalue#Instanceofbytesprint(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'tconcatstrtobytes

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

        'one'+b'two'>>>Traceback...TypeError:canonlyconcatenatestr(not"bytes")tostr

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

        assertb'red'>b'blue'assert'red'>'blue'

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

        assert'red'>b'blue'

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

        assertb'blue'<'red'

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

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

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

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

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

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

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

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

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

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

        withopen('data.bin','w')asf:f.write(b'?????')>>>Traceback...TypeError:write()argumentmustbestr,notbytes

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

        withopen('data.bin','wb')asf:f.write(b'?????')

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

        withopen('data.bin','r')asf:data=f.read()

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

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

        withopen('data.bin','rb')asf:data=f.read()assertdata==b'?????'

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

        withopen('data.bin','r',encoding='cp1252')asf:data=f.read()assertdata=='?òó??'

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

        要點

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

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

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

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

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

        以上內(nèi)容為大家介紹了如何理解Python中bytes與str的區(qū)別,希望對大家有所幫助,如果想要了解更多Python相關(guān)知識,請關(guān)注IT培訓(xùn)機構(gòu):千鋒教育。http://m.2667701.com/

        聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
        10年以上業(yè)內(nèi)強師集結(jié),手把手帶你蛻變精英
        請您保持通訊暢通,專屬學(xué)習(xí)老師24小時內(nèi)將與您1V1溝通
        免費領(lǐng)取
        今日已有369人領(lǐng)取成功
        劉同學(xué) 138****2860 剛剛成功領(lǐng)取
        王同學(xué) 131****2015 剛剛成功領(lǐng)取
        張同學(xué) 133****4652 剛剛成功領(lǐng)取
        李同學(xué) 135****8607 剛剛成功領(lǐng)取
        楊同學(xué) 132****5667 剛剛成功領(lǐng)取
        岳同學(xué) 134****6652 剛剛成功領(lǐng)取
        梁同學(xué) 157****2950 剛剛成功領(lǐng)取
        劉同學(xué) 189****1015 剛剛成功領(lǐng)取
        張同學(xué) 155****4678 剛剛成功領(lǐng)取
        鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
        董同學(xué) 138****2867 剛剛成功領(lǐng)取
        周同學(xué) 136****3602 剛剛成功領(lǐng)取
        相關(guān)推薦HOT
        灵武市| 大城县| 武川县| 类乌齐县| 嘉义市| 贵南县| 永昌县| 微博| 博乐市| 华安县| 贺兰县| 马关县| 积石山| 迁安市| 贵定县| 阳山县| 龙泉市| 汉川市| 玉门市| 龙口市| 久治县| 天水市| 朝阳市| 成武县| 抚顺县| 惠来县| 资溪县| 佛学| 武清区| 安徽省| 阿尔山市| 西昌市| 纳雍县| 洪泽县| 左云县| 鹰潭市| 山阳县| 五家渠市| 松桃| 固原市| 常山县|