天天看點

Python裡的string 和 unicode 差別講得很明白的文章

先要弄清楚的是,在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)