摘要:最近使用處理一些網(wǎng)絡(luò)相關(guān)的問題,被相關(guān)的一系列編碼問題搞得一頭霧水。與接下來是中對于字符串的處理。中的和在中,其類型規(guī)定了底層的數(shù)據(jù)結(jié)構(gòu),是位整數(shù)串,也即跟語言中的字符串類似。這些問題在中得到解決。
最近使用 Python 2 處理一些網(wǎng)絡(luò)相關(guān)的問題,被 Unicode, String 相關(guān)的一系列編碼問題搞得一頭霧水。在這里整理一下相關(guān)的概念吧。
ASCII Unicode UTF8首先是與 Python 無關(guān)的編碼問題。在這里理清楚這幾個(gè)常見的名詞:ASCII, Unicode, UTF8 之間的關(guān)系。
我們知道,為了使用計(jì)算機(jī)處理字符,需要將字符編碼為數(shù)字。對于英文字符,128 個(gè)數(shù)字就夠了,其中最常見的英文字符編碼方案就是 ASCII,該方案規(guī)定了使用 7 位二進(jìn)制數(shù)編碼英文字符的方案。
對于非英文字符,特別是漢語這種有超大字符集的語言,需要需要一個(gè)很大的編碼表將字符編碼為數(shù)字。競爭之后現(xiàn)在通用的方案是 Unicode,該方案的目標(biāo)是覆蓋所有人類語言符號。也就是說,Unicode 定義了一個(gè)從任意字符到數(shù)字的一一映射關(guān)系。
對于 ASCII 而言,一個(gè)字符(使用 7 位編碼)占用一個(gè)字節(jié)(8 位)就夠了,可以簡單地用這個(gè)字節(jié)表示一個(gè)無符號整數(shù)來代表編碼,浪費(fèi)并不大。但是對于 Unicode 而言,由于碼表太大,需要很多字節(jié)才能表示一個(gè) Unicode 編碼數(shù)字,而且 Unicode 是一個(gè)成長中的項(xiàng)目,其碼表不斷擴(kuò)充。因此,如何用字節(jié)表示 Unicode 編碼數(shù)字就成了一個(gè)問題,UTF-8 就是解決這個(gè)問題的方案之一。該方案是一種變長方案,使用不定長的字節(jié)表示一個(gè)數(shù)字。方案對于包含在 ASCII 碼表中的字符只使用 1 個(gè)字節(jié)進(jìn)行編碼,對于非英語拼音語言符號通常使用 2 個(gè)字節(jié)編碼,漢字通常使用 3 個(gè)字節(jié)進(jìn)行編碼。
如果接觸過信息論,可以很容易的理解變長編碼是如何做到的。如果讀者沒有接觸過信息論,這里展示一種簡陋的變長編碼方案,方便讀者理解。
第一個(gè)字節(jié)總是使用無符號整數(shù)表示。當(dāng)數(shù)值位于 [0,254] 中時(shí),這個(gè)字節(jié)的代表的數(shù)值就是編碼的數(shù)值。但當(dāng)數(shù)值是 255 時(shí),不表示這個(gè)數(shù)字是 255,而是表示這個(gè)數(shù)字加上之后兩位(16 bit) 代表的數(shù)之后才是編碼的數(shù)字,于是這個(gè)邊長方案能使用 1~3 字節(jié)編碼 [0, (2 ^ 16 - 1) + (2 ^ 8 - 1)] 之間的數(shù)字。
總結(jié)而言就是,Unicode 是一個(gè)字符到數(shù)字映射表,而 UTF-8 是數(shù)字到字節(jié)的編碼方案。ASCII 由于只使用一個(gè)字節(jié),通常不太強(qiáng)調(diào)其數(shù)字的編碼方案。
Python 與 Unicode接下來是 Python 中對于字符串的處理。
python 2 中的 str 和 unicode在 Python 2 中,其 str 類型規(guī)定了底層的數(shù)據(jù)結(jié)構(gòu),是 8 位整數(shù)串,也即跟 C 語言中的字符串類似。而 unicode 類型是整數(shù)串,并不規(guī)定整數(shù)的位數(shù)或保存方式。unicode.encode() 方法在指定一種編碼方式之后返回一個(gè) str 對象,即為這個(gè) unicode 字符串在該編碼方式之下的字節(jié)表示。
用例子說明這個(gè)問題:
# python 2 us = u"你好" assert(len(us) == 2) # us 是整數(shù)串,共有兩個(gè)整數(shù),代表兩個(gè)字符 s = us.encode("utf8") assert(len(s) == 6) # 使用 utf8 編碼之后,每個(gè)漢字用 3 個(gè)字節(jié)表示,共 6 個(gè)字節(jié)
僅僅是這樣,并不會引起太大的混淆。一個(gè)問題是 python 2 的字符串是可以被初始化為非英文字符的:
# python 2 s = "你好" assert(len(s) == 6)
這種情況下解釋器會自動(dòng)完成編碼工作,具體編碼方式筆者認(rèn)為用戶不應(yīng)該知道,而且筆者認(rèn)為這種用法可能不是一種很好的用法。
更加糟糕的是,python 2 的 print 語句表現(xiàn)有時(shí)候會有些神奇:
# python 2 print "你好" # 得到 你好 print u"你好" # 得到 你好 print ["你好"] # 得到 ["xe4xbdxa0xe5xa5xbd"] print [u"你好"] # 得到 [u"u4f60u597d"]
也就是,只有當(dāng)直接 print str 或者 print unicode 的時(shí)候能夠正常輸出中文,其他情況下, print [str] 會輸出 "str", print [unicode] 會輸出 u"unicode"。這些打印結(jié)果看上去會讓人懷疑沒有解碼,實(shí)際上是 print 語句的行為而已。
python 3 中的 byte 和 str在 python 2 中,str 是一種底層數(shù)據(jù)結(jié)構(gòu),類似于比特串,但 string 這個(gè)英語單詞的意思是字符串,容易引起混淆,如 unicode.encode() 返回值是一個(gè) str,邏輯上并不恰當(dāng)。
這些問題在 python 3 中得到解決。python 2 中的 str 類型相當(dāng)于 python 3 中的 bytes 類型, bytes 這個(gè)名字明確的指出這是字節(jié)串,并且不指定字節(jié)串代表什么東西。而 python 3 中的 str 類似于 python 2 中的 unicode 類型, 不再指定底層編碼規(guī)則。str.encode() 返回一個(gè) bytes 類型也更加符合邏輯。
用例子說明:
# python 3 s = "你好“ assert(len(s) == 2) bs = s.encode("utf8") assert(len(s) == 6)
Python 3 中的 print 函數(shù)一般總是可以正常打印 str,而不是輸出碼值。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/45545.html
摘要:而他們的中文釋義,就是對新手的最大陷阱編碼。而碼,也就是美國信息交換標(biāo)準(zhǔn)碼,年發(fā)布,位字符編碼中影響最大的一種。 編碼,還是編碼! python2的直鉤——編碼異常 當(dāng)你用python打開一篇中文文檔,準(zhǔn)備讀取里面的數(shù)據(jù)開始實(shí)驗(yàn)...當(dāng)你處理好你的數(shù)據(jù),打算打印出易于閱讀的結(jié)果給boss檢查...甚至當(dāng)你剛剛開始編寫自己的代碼,就寫了一句話... text = 什么鬼 只要你開始運(yùn)行自...
摘要:預(yù)告一下,下一篇你真的知道的字符串怎么用嗎將會展開介紹,敬請期待字符串序列是一種不可變序列,這意味著它不能像可變序列一能,進(jìn)行就地修改。例如,在字符串的基礎(chǔ)上拼接,得到字符串,新的字符串是一個(gè)獨(dú)立的存在,它與基礎(chǔ)字符串并沒有關(guān)聯(lián)關(guān)系。 showImg(https://segmentfault.com/img/bVbjGGr?w=6016&h=4000); 在《詳解Python拼接字符串...
摘要:預(yù)告一下,下一篇你真的知道的字符串怎么用嗎將會展開介紹,敬請期待字符串序列是一種不可變序列,這意味著它不能像可變序列一能,進(jìn)行就地修改。例如,在字符串的基礎(chǔ)上拼接,得到字符串,新的字符串是一個(gè)獨(dú)立的存在,它與基礎(chǔ)字符串并沒有關(guān)聯(lián)關(guān)系。 showImg(https://segmentfault.com/img/bVbjGGr?w=6016&h=4000); 在《詳解Python拼接字符串...
閱讀 803·2023-04-26 00:30
閱讀 2712·2021-11-23 09:51
閱讀 1059·2021-11-02 14:38
閱讀 2617·2021-09-07 10:23
閱讀 2257·2021-08-21 14:09
閱讀 1405·2019-08-30 10:57
閱讀 1615·2019-08-29 11:20
閱讀 1163·2019-08-26 13:53