(三)Python基礎2:瞭解字元編碼
阿新 • • 發佈:2018-11-25
# 瞭解字元編碼 # 字串也是一種資料型別,但是,字串比較特殊的是還有一個編碼問題。 # 因為計算機只能處理數字,如果要處理文字,就必須先把文字轉換為數字才能處理。 # 最早的計算機在設計時採用8個位元(bit)作為一個位元組(byte),所以,一個位元組能表示的最大的整數就是255(二進位制11111111=十進位制255), # 如果要表示更大的整數,就必須用更多的位元組。比如兩個位元組可以表示的最大整數是65535,4個位元組可以表示的最大整數是4294967295。 # 由於計算機是美國人發明的,因此,最早只有127個字元被編碼到計算機裡,也就是大小寫英文字母、數字和一些符號, # 這個編碼表被稱為ASCII編碼,比如大寫字母A的編碼是65,小寫字母z的編碼是122。 # 但是要處理中文顯然一個位元組是不夠的,至少需要兩個位元組,而且還不能和ASCII編碼衝突,所以,中國製定了GB2312編碼,用來把中文編進去。 # 你可以想得到的是,全世界有上百種語言,日本把日文編到Shift_JIS裡,韓國把韓文編到Euc-kr裡, # 各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文字中,顯示出來會有亂碼。 # 因此,Unicode應運而生。Unicode把所有語言都統一到一套編碼裡,這樣就不會再有亂碼問題了。 # Unicode標準也在不斷髮展,但最常用的是用兩個位元組表示一個字元(如果要用到非常偏僻的字元,就需要4個位元組)。 # 現代作業系統和大多數程式語言都直接支援Unicode。 # 現在,捋一捋ASCII編碼和Unicode編碼的區別:ASCII編碼是1個位元組,而Unicode編碼通常是2個位元組。 # 字母A用ASCII編碼是十進位制的65,二進位制的01000001; # 字元0用ASCII編碼是十進位制的48,二進位制的00110000,注意字元'0'和整數0是不同的; # 漢字中已經超出了ASCII編碼的範圍,用Unicode編碼是十進位制的20013,二進位制的01001110 00101101。 # 你可以猜測,如果把ASCII編碼的A用Unicode編碼,只需要在前面補0就可以,因此,A的Unicode編碼是00000000 01000001。 # 新的問題又出現了:如果統一成Unicode編碼,亂碼問題從此消失了。但是,如果你寫的文字基本上全部是英文的話, # 用Unicode編碼比ASCII編碼需要多一倍的儲存空間,在儲存和傳輸上就十分不划算。 # 所以,本著節約的精神,又出現了把Unicode編碼轉化為“可變長編碼”的UTF-8編碼。 # UTF-8編碼把一個Unicode字元根據不同的數字大小編碼成1-6個位元組, # 常用的英文字母被編碼成1個位元組,漢字通常是3個位元組,只有很生僻的字元才會被編碼成4-6個位元組。 # 如果你要傳輸的文字包含大量英文字元,用UTF-8編碼就能節省空間: # 三種編碼字元比較 # 字元 ASCII Unicode UTF-8 # A 01000001 00000000 01000001 01000001 # 中 x 01001110 00101101 11100100 10111000 10101101 # 1. 在最新的Python 3版本中,字串是以Unicode編碼的,也就是說,Python的字串支援多語言,例如: print('包含中文的str') # 2. ord()函式獲取字元的整數表示 print(ord('A')) # 65 print(ord('中')) # 20013 # 3. chr()函式把編碼轉換為對應的字元 print(chr(66)) # B print(chr(25991)) # 文 print(chr(0x43)) # C # 如果知道字元的整數編碼,還可以用十六進位制這麼寫str: print('\u4e2d\u6587') # '中文' # 4. str => bytes # 首先區分'ABC'和 b'ABC' # 前者是str,字串,因為本文字是Unicode編碼,所以前者'ABC'每個字元佔兩個位元組 # 後者,位元組碼,雖然內容顯示得和前者一樣,但bytes的每個字元都只佔用一個位元組 # 如果不理解,再返回最上面理解位元組和不同編碼所佔的位元組數的區別 # a. 純英文的str => bytes # 以Unicode表示的str通過encode()方法可以編碼為指定的bytes,例如: print(b'ABC') # b'ABC' print('ABC'.encode('ascii')) # b'ABC' # b. 含有中文的str => bytes # print('中文'.encode('ascii')) # 報錯 # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) print('中文'.encode('utf-8')) # b'\xe4\xb8\xad\xe6\x96\x87' # 意思是純英文的str可以用ASCII編碼為bytes,內容是一樣的,含有中文的str可以用UTF-8編碼為bytes。 # 含有中文的str無法用ASCII編碼,因為中文編碼的範圍超過了ASCII編碼的範圍,Python會報錯。 # c. 在bytes中,無法顯示為ASCII字元的位元組,用\x##顯示。能顯示的就是指ASCII碼對照表上能查到的(0-127) http://ascii.911cha.com/ # 5. bytes => str # 要把bytes變為str,就需要用decode()方法 print(b'ABC'.decode('ascii')) # ABC print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')) # 中文 ################################################################################### # 這裡有一個問題要注意: # 如果輸入 b'\xe4\xb8\xad\xff'.decode('utf-8'), 會報錯 # Traceback (most recent call last): # ... # UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte # 不是所有位元組碼都能正常被utf-8編碼識別 如這裡的0xff utf8str = b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore') print(utf8str) # 中 print(utf8str.encode('utf-8')) # b'\xe4\xb8\xad', 不能識別的 0xff被捨棄了 # 可以先記下, 一般不會用位元組碼直接轉為utf-8編碼, 後面接觸到Base64編碼處理再說 # 編碼問題看不懂不用頭疼,以後用到時慢慢理解 ^_^ ###################################################################################