Python學習-str與byte類型以及編碼
Python 3最重要的新特性之一是對字符串和二進制數據流做了明確的區分。文本總是Unicode
,由str
類型表示,二進制數據則由bytes
類型表示。Python 3不會以任意隱式的方式混用str
和bytes
,你不能拼接字符串和字節流,也無法在字節流裏搜索字符串(反之亦然),也不能將字符串傳入參數為字節流的函數(反之亦然)。
編碼發展的歷史
在談bytes
和str
之前,需要先說說關於編碼是如何發展的。。
在計算機歷史的早期,美國為代表的英語系國家主導了整個計算機行業,26個英文字母組成了多樣的英語單詞、語句、文章。因此,最早的字符編碼規範是ASCII碼,一種8位即1個字節的編碼規範,它可以涵蓋整個英語系的編碼需要。
編碼是什麽?編碼就是把一個字符用一個二進制來表示。我們都知道,所有的東西,不管是英文、中文還是符號等等,最終存儲在磁盤上都是01010101這類東西。在計算機內部,讀取和存儲數據歸根結底,處理的都是0和1組成的比特流。問題來了,人類看不懂這些比特流,如何讓這些010101對人類變得可讀呢?於是出現了字符編碼,它是個翻譯機,在計算機內部某個地方,透明的幫我們將比特流翻譯成人類可以直接理解的文字。對於一般用戶,不需要知道這個過程是什麽原理,是怎麽執行的。但是對於程序員卻是個必須搞清楚的問題。
以ASCII
編碼為例,它規定1個字節8個比特位代表1個字符的編碼,也就是“00000000”這麽寬,一個一個字節的解讀。例如:01000001表示大寫字母A,有時我們會“偷懶"的用65這個十進制來表示A在ASCII
後來,計算機得到普及,中文、日文、韓文等等國家的文字需要在計算機內表示,ASCII的255位遠遠不夠,於是標準組織制定出了叫做UNICODE的萬國碼,它規定任何一個字符(不管哪國的)至少以2個字節表示,可以更多。其中,英文字母就是用2個字節,而漢字是3個字節。這個編碼雖然很好,滿足了所有人的要求,但是它不兼容ASCII
,同時還占用較多的空間和內存。因為,在計算機世界更多的字符是英文字母,明明可以1個字節就能夠表示,非要用2個。
於是UTF-8
編碼應運而生,它規定英文字母系列用1個字節表示,漢字用3個字節表示等等。因此,它兼容ASCII
UTF-8
很快就得到了廣泛的應用。
在編碼的發展歷程中,我國還創造了自己的編碼方式,例如GBK
,GB2312
,BIG5
。他們只局限於在國內使用,不被國外認可。在GBK
編碼中,中文漢字占2個字節。
byte和str之間的異同:
回到bytes
和str
的身上。bytes
是一種比特流,它的存在形式是01010001110這種。我們無論是在寫代碼,還是閱讀文章的過程中,肯定不會有人直接閱讀這種比特流,它必須有一個編碼方式,使得它變成有意義的比特流,而不是一堆晦澀難懂的01組合。因為編碼方式的不同,對這個比特流的解讀也會不同,對實際使用造成了很大的困擾。
1 s = ‘中文‘ 2 print(type(s)) #<class ‘str‘> 3 b = bytes(s,encoding=‘utf-8‘,errors=‘strict‘) 4 print(b) #b‘\xe4\xb8\xad\xe6\x96\x87‘ 5 print(type(b)) #<class ‘bytes‘> 6 s2 = str(b,encoding=‘utf-8‘,errors=‘strict‘) 7 print(s2) #中文 8 print(type(s2)) #<class ‘str‘>
從例子可以看出,s
是個字符串類型。Python有個內置函數bytes()
可以將字符串str
類型轉換成bytes
類型,b
實際上是一串01的組合,但為了在ide環境中讓我們相對直觀的觀察,它被表現成了b‘\xe4\xb8\xad\xe6\x96\x87‘
這種形式,開頭的b
表示這是一個bytes
類型。\xe4
是十六進制的表示方式,它占用1個字節的長度,因此”中文“被編碼成utf-8
後,我們可以數得出一共用了6個字節,每個漢字占用3個,這印證了上面的論述。在使用內置函數bytes()
的時候,必須明確encoding
的參數,不可省略,str()
也類似。
我們都知道,字符串類str
裏有一個encode()
方法,它是從字符串向比特流的編碼過程。而bytes
類型恰好有個decode()
方法,它是從比特流向字符串解碼的過程。除此之外,我們查看Python源碼會發現bytes
和str
擁有幾乎一模一樣的方法列表,最大的區別就是encode
和decode
。
從實質上來說,字符串在磁盤上的保存形式也是01的組合,也需要編碼解碼。
總結:
1、在將字符串寫入磁盤或者從磁盤讀取字符串的時候,Python會自動的完成編碼和解碼的工作。
2、在使用bytes()
的時候,實際就是告訴Python,不需要Python幫你進行編碼,你會手動對輸入的字符串進行編碼,並且可以指定編碼格式。
3、在Python 3中對byte和str進行了嚴格的區分,不能在需要byte類型參數的時候,使用str類型參數。
兩種方式:
1 #將str轉換為byte 2 unicode_string = ‘中文‘ 3 print(type(unicode_string)) #<class ‘str‘> 4 #第一種 5 bytearray = unicode_string.encode() #def encode(self, encoding=‘utf-8‘, errors=‘strict‘),默認就是‘utf-8‘的編碼方式 6 print(bytearray) #b‘\xe4\xb8\xad\xe6\x96\x87‘ 7 print(type(bytearray)) #<class ‘bytes‘> 8 #第二種 9 bytearray2 = bytes(unicode_string,encoding=‘utf-8‘,errors=‘strict‘) #def __init__(self, value=b‘‘, encoding=None, errors=‘strict‘) 10 print(bytearray2) #b‘\xe4\xb8\xad\xe6\x96\x87‘ 11 print(type(bytearray2)) #<class ‘bytes‘> 12 13 #將byte轉換為str 14 bytearray = b‘\xe4\xb8\xad\xe6\x96\x87‘ 15 print(type(bytearray)) #<class ‘bytes‘> 16 #第一種 17 unicode_string = bytearray.decode() 18 print(unicode_string) #中文 19 print(type(unicode_string)) #<class ‘str‘> 20 #第二種 21 unicode_string2 = str(bytearray,encoding=‘utf-8‘,errors=‘strict‘) 22 print(unicode_string2) #中文 23 print(type(unicode_string2)) #<class ‘str‘>
參考:
Chown-Jane-Y
Python 3最重要的新特性之一是對字符串和二進制數據流做了明確的區分。文本總是Unicode
,由str
類型表示,二進制數據則由bytes
類型表示。Python 3不會以任意隱式的方式混用str
和bytes
,你不能拼接字符串和字節流,也無法在字節流裏搜索字符串(反之亦然),也不能將字符串傳入參數為字節流的函數(反之亦然)。
Python學習-str與byte類型以及編碼