1. 程式人生 > >Python2和3的字串編碼差別

Python2和3的字串編碼差別

本文用實驗詳細地演示了Python2和Python3在字串編碼上的區別。

在Python2中,字串字面量對應於8位的字元或面向位元組編碼的位元組字面量。這些字串的一個重要限制是它們無法完全地支援國際字符集和Unicode編碼。為了解決這種限制,Python2對Unicode資料使用了單獨的字串型別。要輸入Unicode字串字面量,要在第一個引號前加上前最'u'

Python2中還有一種稱為位元組字面量的字串型別,它是指一個已經編碼的字串字面量,在Python2中位元組字面量和普通字串沒有差別,因為在Python2中普通字串實際上就是已經編碼(非Unicode)的位元組字串。

在Python3中,不必加入這個字首字元,否則是語法錯誤,這是因為所有的字串預設已經是Unicode編碼了。如果使用-U

選項執行直譯器,Python2會模擬這種行為(即所有字串字面量將被作為Unicode字元對待,u字首可以省略)。在Python3中,位元組字面量變成了與普通字串不同的型別

~/download/firefox $ python2
Python 2.7.2 (default, Jun 29 2011, 11:17:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> '張俊' #python2 會自動將字串轉換為合適編碼的位元組字串
'\xe5\xbc\xa0\xe4\xbf\x8a'
#自動轉換為utf-8編碼的位元組字串 >>> u'張俊' #顯式指定字串型別為unicode型別, 此型別字串沒有編碼,儲存的是字元在unicode字符集中的程式碼點(序號) u'\u5f20\u4fca' >>> '張俊'.encode('utf-8') #python2 已經自動將其轉化為utf-8型別編碼,因此再次編碼(python2會將該字串當作用ascii或unicode編碼過)會出現錯誤。 Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii'
codec can't decode byte 0xe5 in position 0: ordinal not in range(128) >>> '張俊'.decode('utf-8') #python2 可以正常解碼,返回的字串類是無編碼的unicode型別 u'\u5f20\u4fca' >>> b'張俊' # ‘張俊' 已被python2轉換為utf-8編碼,因此已為位元組字串 '\xe5\xbc\xa0\xe4\xbf\x8a' >>> print '張俊' 張俊 >>> print u'張俊' 張俊 >>> print b'張俊' 張俊 >>> ~/download/firefox $ python3 Python 3.2.2 (default, Sep 5 2011, 04:33:58) [GCC 4.6.1 20110819 (prerelease)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> '張俊' #python3的字串預設為unicode格式(無編碼) '張俊' >>> u'張俊' #由於預設為unicode格式,因此字串不用像python2一樣顯式地指出其型別,否則是語法錯誤。 File "<stdin>", line 1 u'張俊' ^ SyntaxError: invalid syntax >>> type('張俊') #python3中文字字串和位元組字串是嚴格區分的,預設為unicode格式的文字字串 <class 'str'> >>> '張俊'.decode('utf-8') #因為預設的文字字串為unicode格式,因此文字字串沒有decode方法 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'str' object has no attribute 'decode' >>> '張俊'.encode('utf-8') #將文字字串編碼,轉換為已編碼的位元組字串型別 b'\xe5\xbc\xa0\xe4\xbf\x8a' >>> type('張俊'.encode('utf-8')) <class 'bytes'> >>> print ('張俊'.encode('utf-8')) #對於已編碼的位元組字串,文字字串的許多特性和方法已經不能使用。 b'\xe5\xbc\xa0\xe4\xbf\x8a' >>>print ('張俊'.encode('utf-8')) b'\xe5\xbc\xa0\xe4\xbf\x8a' >>> print ('張俊'.encode('utf-8').decode('utf-8')) #必須將位元組字串解碼後才能打印出來 張俊