Unicode編碼

為了介紹Python的編碼知識,我們先來回顧下計算機發展歷史上文字是如何編碼的。

計算機在美國被髮明之後,一開始需要被儲存的字元個數不多,包括大小寫的英語字母以及常用的標點符號,在7個bit內就能把所有的適用於美國當時要求的字元給列舉出來,這就是ASCII碼,是American Standard Code for Information Interchange的首字母縮寫。

計算機繼續推廣後,在文字記錄上首先遇到的問題就是即使是跟英語相近的語言,比如法語等,它們有很多的字母需要在正常的字母上方加上比如冒號等符號,例如éÍ ,那7個bit就不夠用了。於是各個語言就開始在ASCII的基礎上擴充,擴充到了一個位元組,也就是8個bit。法語加上法語自己的一些特殊字母成了一個新的編碼集,俄語加上自己的西裡爾字母也成了一個新的編碼集。這些嘗試在自己語言內部是沒有問題,但是一個文件中需要混合兩種以上的語言時候,就出現錯誤了,沒有一個編碼集能夠覆蓋全部語言。

這就是後來為什麼又把編碼擴充到了兩個位元組,或者16個bit的原因,用一個超大的編碼集把所有的文字都包含進來,這種努力直到字符集的長度變為了21個bit,也就是字元編碼的範圍從00x10FFFF,才真正的把世界上所有的文字都囊括進去了。最後的這個編碼標準,就是ISO 10646,或者也可以說是Unicode

回顧完了歷史,我們來看什麼是UTF-8。現有的ISO10646解決了編碼的終極問題,任何字元都可以在這個編碼集中找到自己的位置,但是如果我們用這種方法來儲存文字的話,就會有一個問題了,太浪費空間。因為常用的字元都可以在8個位元或者16個位元內找到自己的位置,假如我們都有21個位元來儲存字元的話,效率大概只有30%-50%,所有就出現了類似UTF-8這樣的編碼,它也是現行被採用最多的編碼方式。

UTF-8UTF的意思是Unicode Transformation Format-Unicode轉換格式,8的意思是8位元編碼。它的規則如下,

  1. 假如編碼數字<128,就採用用相應的編碼值。
  2. 假如編碼數字>128,就分別用2、3或4個位元組來表示,其中每個位元組的取值範圍在128-255,也即是最高位都為1,是為了跟ASCII區分開,ASCII的位元組最高位bit是0

Python 3以後,字串儲存都是以unicode的方式來儲存了,而不像Python 2中那樣字串是預設以bytes來儲存的。

# Python 3
type("f") == type(u"f")  # True, <class 'str'>
type(b"f")               # <class 'bytes'>

# Python 2
type("f") == type(b"f")  # True, <type 'str'>
type(u"f")               # <type 'unicode'>