先要弄清楚的是,在python裡,string object和unicode object是兩種不同的類型。
原文部落客--http://blog.csdn.net/feisan
string object是由characters組成的sequence,而unicode object是Unicode code units組成的sequence。
string裡的character是有多種編碼方式的,比如單位元組的ASCII,雙位元組的GB2312等等,再比如UTF-8。很明顯要想解讀string,必需知道string裡的character是用哪種編碼方式,然後才能進行。
Unicode code unit又是什麼東西呢?一個Unicode code unit是一個16-bit或者32-bit的數值,每個數值代表一個unicode符号。在python裡,16-bit的unicode,對應的是ucs2編碼。32-bit對應的是ucs4編碼。是不是感覺string裡character的編碼沒什麼差別?反正我現在腦子裡就是這樣一個印象:在Python裡,ucs2或者ucs4編碼的,我們叫做unicode object,其他編碼的我們就叫做string。
至于python裡的unicode到底是ucs2還是ucs4的,可以在編譯時指定。例如Linux下,要用ucs2做unicode的編碼,可以這樣
# ./configure --enable-unicode=ucs2
# make
# make install
下載下傳的Windows預編譯版本,一般都是ucs2的。要想知道某個python運作環境是ucs2還是ucs4,可以檢視sys.maxunicde,65535就是ucs2的,另一個很大的數值就是ucs4。
下面我們看看string和unicode在python裡的不同
我們先看看在簡體中文Windows 2003系統下,系統編碼是GBK
>>> a = '你好'
>>> a
'/xc4/xe3/xba/xc3'
>>> b = u'你好'
>>> b
u'/u4f60/u597d'
>>> print a
你好
>>> print b
你好
>>> a.__class__
<type 'str'>
>>> b.__class__
<type 'unicode'>
>>> len(a)
4
>>> len(b)
2
在一個系統編碼為UTF-8的Linux環境下
>>> a = '你好'
>>> a
'/xe4/xbd/xa0/xe5/xa5/xbd'
>>> b = u'你好'
>>> b
u'/u4f60/u597d'
>>> print a
你好
>>> print b
你好
>>> a.__class__
<type 'str'>
>>> b.__class__
<type 'unicode'>
>>> len(a)
6
>>> len(b)
2
如何?簡單總結一下:
1、string直接用引号來表示,unicode在引号前加一個u
2、直接輸入的string常量會用系統預設編碼方式來編碼,例如在GBK環境下,'你好'會編碼成'/xc4/xe3/xba/xc3',而在UTF-8環境下就成了'/xe4/xbd/xa0/xe5/xa5/xbd'。
3、len(string)傳回string的位元組數,len(unicode)傳回的是字元數
4、很重要的一點,print unicode不會亂碼。現在我們常用的Linux、Windows系統,都是支援unicode的,版本太老的不算。比如Windows 2003支援ucs2,是以在中文Windows2003下,除了可以正常顯示預設的GBK編碼外,還可以正常顯示ucs2編碼。舉個例子,還是在中文Windows 2003的GBK環境下:
>>>a = '/xe4/xbd/xa0/xe5/xa5/xbd' # UTF-8的'你好'
>>> print a
浣犲ソ
>>> b = unicode(a, "UTF-8")
>>> b
u'/u4f60/u597d'
>>> print b
你好
應該明白了吧?
下面再說說string和unicode的互相轉換,什麼unicode()、decode()、encode()、codecs之類的。
繼續。
先說一下,前面提到,print(string)的時候,如果string是按目前環境編碼方式編碼的,可以正常輸出,不會亂碼;如果string不是目前編碼的,就會亂碼。而print(unicode)是不會亂碼的。why?應為print(unicode)的時候,會把unicode先轉成目前編碼,然後再輸出。我沒看過print的源碼,不過估計是這樣的。
string轉unicode或者unicode轉string,是很常見的操作。
string和unicode都有decode()和encode()方法。decode是string2unicode,encode自然就是unicode2string。看個例子(中文Windows2003下):
>>> a = '你好'
>>> a
'/xc4/xe3/xba/xc3'
>>> b = u'你好'
>>> c = a.decode('gbk') #gbk string to unicode
>>> b == c
True
>>> c
u'/u4f60/u597d'
>>> d = b.encode('gbk') #unicode to gbk string
>>> d == a
True
>>> d
'/xc4/xe3/xba/xc3'
>>> e = b.encode('utf-8') #unicode to utf-8 string
>>> e
'/xe4/xbd/xa0/xe5/xa5/xbd'
decode或者encode的時候,如果不指定編碼方式,會按照預設編碼方式來處理。檢視、設定預設編碼方式可以這樣做:
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.setdefaultencoding('gbk')
上面調用sys.setdefaultencoding()的時候先reload一下sys module,原因是python啟動時預設會import site.py, 而site.py會del sys.setdefaultencoding(),是以需要reload(sys)。具體可以看看site.py的源碼。
接下來說說unicode()函數。其實unicode函數就是調用string的decode()方法,把string轉成unicode,例如:
>>> a = '你好'
>>> b = unicode(a)
>>> b
u'/u4f60/u597d'
>>> c = a.decode('gbk')
>>> c
u'/u4f60/u597d'
>>> print b, c, b==c
你好 你好 True
下一部分說說codec
最後說說關于codecs。所謂的codec就是編碼器和解碼器(encoder and decoder)的集合。除了各種字元串編碼的codec,還有各種檔案格式的codec,比如壓縮、解壓縮的,圖像的,音頻的,等等。我們這裡說的當然是跟字元串編碼相關的了。
看看代碼
>>> import codecs
>>> gbk=codecs.lookup('gbk')
>>> gbk
<codecs.CodecInfo object for encoding gbk at 0xad3ea0>
>>> gbk.decode("你好")
(u'/u4f60/u597d', 4)
>>> gbk.encode(u'/u4f60/u597d')
('/xc4/xe3/xba/xc3', 2)