標籤:自己 odi .com mil 進位 div 手動 今天 作用
學習Python,字元編碼間的轉換是繞不過去的一隻攔路虎,不把編碼徹底搞明白,總有一天它會猝不及防坑你一把。
Python2.x和Python3.x在字元編碼的設定上也有很大區別(Python3未來將是主流,所以Python3為主),今天我們就來一起學習下。
上一篇文章裡我已經簡述了Python的常見編碼了,這裡就不再贅述了,還不清楚的小夥伴可以先去看下: http://www.cnblogs.com/schut/p/8406897.html
一、Unicode 和 UTF-8的糾葛
Unicode 起到了2個作用:
- 直接支援全球所有語言,每個國家都可以不用再使用自己之前的舊編碼了,用unicode就可以了。(就跟英語是全球統一語言一樣)
- unicode包含了跟全球所有國家編碼的映射關係。
Unicode解決了字元和二進位的對應關係,但是使用unicode表示一個字元,太浪費空間。例如:利用unicode表 示“Python”需要12個位元組才能表示,比原來ASCII表示增加了1倍。由於電腦的記憶體比較大,並且字串在內容中表示時也不會特別大,所以內容可以使用unicode來處理,但是儲存和網路傳輸時一般資料都會非常多,那麼增加1倍將是無法容忍的!!!
為瞭解決儲存和網路傳輸的問題,出現了Unicode Transformation Format,學術名UTF,即:對unicode中的進行轉換,以便於在儲存和網路傳輸時可以節省空間的!
UTF-8: 使用1、2、3、4個位元組表示所有字元;優先使用1個字元、無法滿足則使增加一個位元組,最多4個位元組。英文佔1個位元組、歐洲語系佔2個、東亞佔3個,其它及特殊字元佔4個。
UTF-16: 使用2、4個位元組表示所有字元;優先使用2個位元組,否則使用4個位元組表示。
UTF-32: 使用4個位元組表示所有字元。
總結:UTF 是為unicode編碼 設計 的一種 在儲存 和傳輸時節省空間的編碼方案。
二、字元在硬碟上的儲存
首先要明確的一點就是,無論以什麼編碼在記憶體裡顯示字元,存到硬碟上都是2進位。理解這一點很重要。
比如:
ascii編碼(美國): l 0b1101100 o 0b1101111 v 0b1110110 e 0b1100101 GBK編碼(中國): 老 0b11000000 0b11001111 男 0b11000100 0b11010000 孩 0b10111010 0b10100010
還要注意的一點是,要注意的是,存到硬碟上時是以何種編碼存的,再從硬碟上讀出來時,
就必須以何種編碼讀(開頭聲明或轉換),要不然就亂了。
三、編碼的轉換
雖然有了unicode and utf-8 ,但是由於曆史問題,各個國家依然在大量使用自己的編碼,
比如中國的windows,預設編碼依然是gbk,而不是utf-8。
基於此,如果中國的軟體出口到美國,在美國人的電腦上就會顯示亂碼,因為他們沒有gbk編碼。
所以該怎麼辦呢?
還記得我們講unicode其中一個功能是其包含了跟全球所有國家編碼的映射關係,這時就派上用場了。
無論你以什麼編碼儲存的資料,只要你的軟體在把資料從硬碟讀到記憶體裡,轉成unicode來顯示,就可以了。
由於所有的系統、程式設計語言都預設支援unicode,那你的gbk軟體放到美國電腦上,載入到記憶體裡,變成了unicode,
中文就可以正常展示啦。
Python3執行過程
- 解譯器找到代碼檔案,把代碼字串按檔案頭定義的編碼載入到記憶體,轉成unicode
- 把代碼字串按照文法規則進行解釋
- 所有的變數字元都會以unicode編碼聲明
在py3上 把你的代碼以utf-8編寫, 儲存,然後在windows上執行。
發現可以正常執行!
其實utf-8編碼之所以能在windows gbk的終端下顯示正常,是因為到了記憶體裡python解譯器把utf-8轉成了unicode ,
但是這隻是python3, 並不是所有的程式設計語言在記憶體裡預設編碼都是unicode,比如 萬惡的python2 就不是,
是ASCII,想寫中文,就必須聲明檔案頭的coding為gbk or utf-8, 聲明之後,python2解譯器
僅以檔案頭聲明的編碼去解釋你的代碼,載入到記憶體後,並不會主動幫你轉為unicode,也就是說,你的檔案編碼是utf-8,
載入到記憶體裡,你的變數字串就也是utf-8, 這意味著什嗎?意味著,你以utf-8編碼的檔案,在windows是亂碼。
其實亂是正常的,不亂才不正常,因為只有2種情況 ,你的windows上顯示才不會亂。Python2並不會自動的把檔案編碼轉為unicode存在記憶體裡,
- 字串以GBK格式顯示
- 字串是unicode編碼
所以我們只有手動轉,Python3 自動把檔案編碼轉為unicode必定是調用了什麼方法,這個方法就是,decode(解碼) 和encode(編碼)。
方法如下:
UTF-8 --> decode 解碼 --> Unicode
Unicode --> encode 編碼 --> GBK / UTF-8
例如:
#!/usr/bin/env python3#-*- coding:utf-8 -*-# write by congcongs = ‘匆匆‘print(s)s1 = s.decode("utf-8") # utf-8 轉成 Unicode,decode(解碼)需要註明當前編碼格式print(s1,type(s1))s2 = s1.encode("gbk") # unicode 轉成 gbk,encode(編碼)需要註明產生的編碼格式print(s2,type(s2))s3 = s1.encode("utf-8") # unicode 轉成 utf-8,encode(編碼)註明產生的編碼格式print(s3,type(s3))
規則如下:
四、如何驗證編碼轉對了呢?
1、查看資料類型,python 2 裡有專門的unicode 類型
2、查看unicode編碼映射表
unicode字元是有專門的unicode類型來判斷的,但是utf-8,gbk編碼的字元都是str,
你如果分辨出來的當前的字串資料是何種編碼的呢? 有人說可以通過位元組長度判斷,
因為utf-8一個中文佔3位元組,gbk一個佔2位元組。
看輸出的位元組個數,也能大體判斷是什麼類型。精確的驗證一個字元的編碼呢,就是拿這些16進位的數跟編碼錶裡去匹配。
詳細過程可以看這裡:https://www.luffycity.com/python-book/di-3-zhang-python-ji-chu-2014-wen-jian-cao-4f5c26-han-shu/33-zi-fu-bian-ma-zhuan-huan.html
五、Python bytes類型
把8個二進位一組稱為一個byte,用16進位來表示。為的就是讓人們看起來更可讀。我們稱之為bytes類型,即位元組類型。
python2的字串其實更應該稱為位元組串。 通過儲存方式就能看出來, 但python2裡還有一個類型是bytes呀,難道又叫bytes又叫字串?
嗯 ,是的,在python2裡,bytes == str , 其實就是一回事。
除此之外呢, python2裡還有個單獨的類型是unicode , 把字串解碼後,就會變成unicode。
>>> s‘\xe8\xb7\xaf\xe9\xa3\x9e‘ #utf-8>>> s.decode(‘utf-8‘)u‘\u8def\u98de‘ #unicode 在unicode編碼錶裡對應的位置>>> print(s.decode(‘utf-8‘))路飛 #unicode 格式的字元
Python2的預設編碼是ASCII碼,當後來大家對支援漢字、日文、法語等語言的呼聲越來越高時,Python於是準備引入unicode,但若直接把
預設編碼改成unicode的話是不現實的, 因為很多軟體就是基於之前的預設編碼ASCII開發的,編碼一換,那些軟體的編碼就都亂了。所以Python 2
就直接 搞了一個新的字元類型,就叫unicode類型,比如你想讓你的中文在全球所有電腦上正常顯示,在記憶體裡就得把字串存成unicode類型。
>>> s = "路飛">>> s‘\xe8\xb7\xaf\xe9\xa3\x9e‘>>> s2 = s.decode("utf-8")>>> s2u‘\u8def\u98de‘>>> type(s2)<type ‘unicode‘>
Python3 除了把字串的編碼改成了unicode, 還把str 和bytes 做了明確區分, str 就是unicode格式的字元, bytes就是單純二進位啦。
在py3裡看字元,必須得是unicode編碼,其它編碼一律按bytes格式展示。
Python只要出現各種編碼問題,無非是哪裡的編碼設定出錯了
常見編碼錯誤的原因有以下這些:
- Python解譯器的預設編碼
- Python源檔案檔案編碼
- Terminal使用的編碼
- 作業系統的語言設定
最後總結一下:
python3 檔案預設編碼是utf-8 , 字串編碼是 unicode
以utf-8 或者 gbk等編碼的代碼,載入到記憶體,會自動轉為unicode正常顯示。
python2 檔案預設編碼是ascii , 字串編碼也是 ascii , 如果檔案頭聲明了是gbk,那字串編碼就是gbk。
以utf-8 或者 gbk等編碼的代碼,載入到記憶體,並不會轉為unicode,編碼仍然是utf-8或者gbk等編碼。
以上內容搬運和修改自:https://www.luffycity.com/python-book/di-3-zhang-python-ji-chu-2014-wen-jian-cao-4f5c26-han-shu/33-zi-fu-bian-ma-zhuan-huan.html
Python常見字元編碼間的轉換