Python字元編碼

2021-09-07 04:40:39 字數 4442 閱讀 4373

在用python程式設計中,字串有兩種表示方法"string"和 u"string"。

為什麼字串要是用這兩種表達方式。不是僅僅用前一種呢?

使用type()函式檢視,它們各自是str物件和unicode物件。這兩個物件有什麼差別嗎?還有經經常使用到的encode()和decode()又是幹什麼的呢?都說python指令碼使用的是兩位元組編碼,這又是指什麼呢?

要回答上面幾個問題,首先得弄清楚關於編碼的幾個概念:

character set:字符集,是我們人能夠識別的字元。

如ascii規定了127個用乙個位元組能夠表示的字符集。包含英文本母、數字、符號和一些控制字元。當然ascii定義的字符集比較小。

python中的character set基本包含眼下世界上全部是用的字元。如中文、英文、日文字元等等。所以基本上全部的字元都可在python 中進行處理。

code point:計算機是不能直接識別字元的(由於它僅僅能直接識別二進位製碼),所以為了能讓計算機處理和儲存字元,須要將字元對映成乙個數值(由於數值能夠用二進位制表達,計算機從而就能夠識別了),這個數值叫作字元的code point。字元與其code point是一對一對映,unicode非常好的規定了這樣的對映關係。

encode:unicode儘管規定了每乙個字元的code point,但並沒有規定計算機怎樣儲存這些code point。

全部就有了utf-8、gbk、utf-16等編碼格式,它們規定計算機怎樣來儲存這個code point,每乙個編碼格式它們儲存方式都是不同樣的。比如,「中」字的code point為u

+2d2e(u表示unicode,2d2e表示該code point值),使用gbk、big5、utf-8、utf-16四種編碼協議對該code point進行編碼。獲得的實際二進位製表演示樣例如以下:

gbk      big5        utf-8     utf-16

~~\xd6\xd0 \xa4\xa4 \xe4\xb8\xad \x2d\x4e

decode:對實際的二進位制進行解碼。獲取它所代表字元的code point。如「\xd6\xd0」使用gbk解碼,將獲得2d2e(「中」的code point ),假設使用utf-8對其進行解碼。就會出錯。由於它不是用utf-8編碼的。

上面簡介下字元及編碼解碼的概念,可參考博文《字元的編碼與解碼》。

python中使用兩種字串表達方式,是為了區分字元與實際表示字元的二進位制資訊。

unicode物件用來表示字元。它不涉及字元的底層的二進位制編碼資訊。

str物件是用來表示字元的二進位制資訊。乙個unicode物件能夠使用多種編碼格式(如utf8、gbk)編碼(encode)成多個str物件。每乙個str物件表示該字串的一種二進位制表達。多個不同的str物件能夠解碼成相等的unicode物件(表示字串同樣。但記憶體位置不同)。

unicode的存在也是為了解決因採用不同編碼格式導致的一些問題。建議大家使用unicode物件來存放字串,統一格式。

unicode儘管不規定詳細的二進位制資訊,但為了存放每乙個字元的code point值,須要兩個位元組,所以說python採用的是二進位制編碼(不知道這麼理解可對?)。

因為str物件沒有屬性指定它的編碼格式。所以對它進行處理時,僅僅能將它看成乙個位元組串。當對str物件進行列印或解碼時。且不知道它的編碼格式。那麼python僅僅能用預設編碼格式對其進行操作。

假設編碼不匹配,就會出現亂碼或者報錯。

str物件:

稱字串,它是字串使用特定編碼格式進行編碼後的二進位制表達,實際代表用於儲存二進位制資訊的位元組串。

所以稱它為「位元組串」更合適。如

>>> str = '你好'   #採用系統設定的編碼格式對「你好」進行編碼,可通過locale命令檢視。
>>> str '\xe4\xbd\xa0\xe5\xa5\xbd' #當locale設定為utf8時。'你好'的編碼後的二進位制表達,乙個六位元組的位元組串

unicode物件

用於表達「字元」,由於計算機不用直接識別字元,所以使用code point來取代字元。例如以下:

>>> u"你好"

u'\u4f60\u597d'

code point 4f60表示「你」,597d表示「好」。

它僅僅是乙個數值與字元對映,

不用於詳細編碼。

對乙個str物件進行解碼。能夠獲得它表達字串的code point,即unicode物件。對unicode物件進行編碼。可獲得它的實際二進位制表達,即str物件。當想把str物件從一中編碼格式轉換成還有一種編碼格式時,首先得把str轉換成unicode物件。再從unicode物件轉換成第二種編碼格式的str物件。

以下執行乙個str物件從utf8格式到gbk格式的轉換:

>>> str="你好"

>>> str

'\xe4\xbd\xa0\xe5\xa5\xbd' # 採用os的utf8編碼格式

>>> unicode=str.decode("utf8") # 解碼成code point值

>>> unicode

u'\u4f60\u597d'

>>> str_gbk=unicode.encode("gbk") # 將code point編碼成gbk格式

>>> str_gbk

'\xc4\xe3\xba\xc3'

>>> unicode.encode() # 假設編碼不指定格式,將採用系統預設的編碼格式進行編碼。對於decode也一樣。

這裡因為ascii不能對中文字元編碼,所以出錯了。 traceback (most recent call last):   file "", line 1, in unicodeencodeerror: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) >>> u = u"你好"     #字首u自己主動把字串從utf8轉換成unicode格式了 u'\u4f60\u597d'

寫檔案:

>>> file=open("test.txt", "a")

>>> file.write(str)

>>> file.write(str_gbk)

>>> file.write(unicode)

traceback (most recent call last):

file "", line 1, in unicodeencodeerror: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

從上面看。utf8格式的str物件和gbk格式的str物件成功的寫入test.txt檔案,然而在將unicode物件寫入檔案時。出現錯誤了。

這是為什麼呢?

str物件表示字串經編碼後的二進位制資訊,能夠直接寫入檔案。

然後unicode物件表示的是字串的code point值,是抽象的值,用來表示字元,是不能直接寫入檔案的。所以python試圖使用預設的編碼格式ascii。對unicode物件進行編碼,然後將結果存入檔案。可是因為ascii不能對」你好」進行編碼,所以報錯了。

改動系統預設編碼格式:

>>> import sys

>>> reload(sys)

>>> sys.setdefaultencoding("gbk") #不建議這麼用[2]

>>> str(unicode) #使用預設gbk,對unicode("你好")進行編碼,轉成str物件

'\xc4\xe3\xba\xc3'

>>> unicode.encode() #使用預設gbk。對unicode("你好")進行編碼,轉成str物件

'\xc4\xe3\xba\xc3'

>>> "你好".decode() #由於系統使用utf8,所以「你好」是utf8格式的位元組串,使用預設gbk對該位元組串進行解碼,儘管成功執行了,但其結果是不對的。

所以我們須要保證位元組串用什麼格式編碼的。就要用什麼格式解碼。 u'\u6d63\u72b2\u30bd'

參考文獻:

[1] 

bid=284&id=84741

[2] 

[3] 

[4] 

python字元編碼

ascii 碼是乙個位元組,通常只能顯示英文本母和數字。unicode碼為了顯示多種語言產生,但是要占用兩個位元組,顯示文字要占用大量空間 utf 8 為了節約空間而生,英文本元只用乙個位元組儲存,中文字元需要三個位元組 character ascii unicode utf 8 a01000000...

python字元編碼

列印python檔案編碼 import sys print sys.getdefaultencoding 中文的乙個字元unicode占用2個位元組。對在於ascii字元占用1個位元組 utf 8中 中文字元佔3個位元組,英文本元占用1個位元組 編碼和轉碼 unicode不能再解碼了 它是基層的 u...

Python字元編碼

計算機只能處理數字,如果要處理文字,必須先把文字轉化成數字。計算機最早是美國人發明的,所以只有127個字元被編碼到計算機裡面,即大小寫英文本母 數字及一些符號,這個編碼表被稱為ascll表。其中 a 的編碼是65,a 的編碼是97。大本事處理中文乙個位元組是不夠的,至少需要兩個位元組,為了不與asc...