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中的編碼。8個位元位,可以沒有重複的最多表示2的8次方(255)個字元。
後來,計算機得到普及,中文、日文、韓文等等國家的文字需要在計算機內表示,ascii的255位遠遠不夠,於是標準組織制定出了叫做unicode的萬國碼,它規定任何乙個字元(不管哪國的)至少以2個位元組表示,可以更多。其中,英文本母就是用2個位元組,而漢字是3個位元組。這個編碼雖然很好,滿足了所有人的要求,但是它不相容ascii,同時還占用較多的空間和記憶體。因為,在計算機世界更多的字元是英文本母,明明可以1個位元組就能夠表示,非要用2個。
於是utf-8編碼應運而生,它規定英文本母系列用1個位元組表示,漢字用3個位元組表示等等。因此,它相容ascii,可以解碼早期的文件。utf-8很快就得到了廣泛的應用。
在編碼的發展歷程中,我國還創造了自己的編碼方式,例如gbk,gb2312,big5。他們只侷限於在國內使用,不被國外認可。在gbk編碼中,中文漢字佔2個位元組。
bytes和str之間的異同
回到bytes和str的身上。bytes是一種位元流,它的存在形式是01010001110這種。我們無論是在寫**,還是閱讀文章的過程中,肯定不會有人直接閱讀這種位元流,它必須有乙個編碼方式,使得它變成有意義的位元流,而不是一堆晦澀難懂的01組合。因為編碼方式的不同,對這個位元流的解讀也會不同,對實際使用造成了很大的困擾。下面讓我們看看python是如何處理這一系列編碼問題的:
>>
> s =
"中文"
>>
> s
'中文'
>>
>
type
(s)<
class
'str'
>
>>
> b =
bytes
(s, encoding=
'utf-8'
)>>
> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>
>
type
(b)<
class
'bytes'
>
從例子可以看出,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裡有乙個encode()方法,它是從字串向位元流的編碼過程。而bytes型別恰好有個decode()方法,它是從位元流向字串解碼的過程。除此之外,我們檢視python原始碼會發現bytes和str擁有幾乎一模一樣的方法列表,最大的區別就是encode和decode。
從實質上來說,字串在磁碟上的儲存形式也是01的組合,也需要編碼解碼。
如果,上面的闡述還不能讓你搞清楚兩者的區別,那麼記住下面兩幾句話:
在將字串存入磁碟和從磁碟讀取字串的過程中,python自動地幫你完成了編碼和解碼的工作,你不需要關心它的過程。
使用bytes型別,實質上是告訴python,不需要它幫你自動地完成編碼和解碼的工作,而是使用者自己手動進行,並指定編碼格式。
python已經嚴格區分了bytes和str兩種資料型別,你不能在需要bytes型別引數的時候使用str引數,反之亦然。這點在讀寫磁碟檔案時容易碰到。
在bytes和str的互相轉換過程中,實際就是編碼解碼的過程,必須顯式地指定編碼格式。
>>
> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>
>
type
(b)<
class
'bytes'
>
>>
> s1 =
str(b)
>>
> s1
"b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'"
>>
>
type
(s1)
<
class
'str'
>
>>
> s1 =
str(b, encoding=
'utf-8'
)>>
> s1
'中文'
>>
>
type
(s1)
<
class
'str'
>
我們再把字串s1,轉換成gbk編碼的bytes型別:
>>
> s1
'中文'
>>
>
type
(s1)
<
class
'str'
>
>>
> b =
bytes
(s1, encoding=
'gbk'
)>>
> b
b'\xd6\xd0\xce\xc4'
越努力越幸運
python3 中bytes和str型別
轉 python 3最重要的新特性之一是對字串和二進位制資料流做了明確的區分。文字總是unicode,由str型別表示,二進位制資料則由bytes型別表示。python 3不會以任意隱式的方式混用str和bytes,你不能拼接字串和位元組流,也無法在位元組流裡搜尋字串 反之亦然 也不能將字串傳入引數...
python中bytes和str型別的區別
經過一上午的查詢資料。大概理清楚了bytes型別和str型別的區別。bytes型別和str型別在呈現形式有相同之處,如果你print乙個bytes型別的變數,會列印乙個用b開頭,用單引號括起來的序列。比如 c b x80abc twww.cppcns.comype c bytes 我們看到c b x...
Python3中的bytes和str型別
python 3最重要的新特性之一是對字串和二進位制資料流做了明確的區分。文字總是unicode,由str型別表示,二進位制資料則由bytes型別表示。python 3不會以任意隱式的方式混用str和bytes,你不能拼接字串和位元組流,也無法在位元組流裡搜尋字串 反之亦然 也不能將字串傳入引數為位...