python3和python2編碼拾遺

2022-08-18 02:00:19 字數 3717 閱讀 8214

py2編碼

tr和unicode

str和unicode都是basestring的子類。嚴格意義上說,str其實是位元組串,它是unicode經過編碼後的位元組組成的序列。對utf-8編碼的str'苑'使用len()函式時,結果是3,因為utf8編碼的'苑' == '\xe8\x8b\x91'。

而unicode是乙個字串,str是unicode這個字串經過編碼(utf8,gbk等)後的位元組組成的序列。如上面utf8編碼的字串'漢'。

unicode才是真正意義上的字串,對位元組串str使用正確的字元編碼進行解碼後獲得,並且len(u'苑') == 1。

在py2裡,str=bytes。

py2編碼的最大特點是python 2 將會自動的將bytes資料解碼成 unicode 字串

所以在2裡我們可以將位元組與字串拼接。

兩個問題:

1 print '苑昊' :本來存的是'\xe8\x8b\x91\xe6\x98\x8a',為什麼顯示了 苑昊 的明文?

2 位元組串和字串可以拼接?

這就是那些可惡的 unicodeerror 。你的**中包含了 unicode 和 byte 字串,只要資料全部是 ascii 的話,所有的轉換都是正確的,一旦乙個非 ascii 字元偷偷進入你的程式,那麼預設的解碼將會失效,從而造成 unicodedecodeerror 的錯誤。

python 2 悄悄掩蓋掉了 byte 到 unicode 的轉換,讓程式在處理 ascii 的時候更加簡單。你復出的代價就是在處理非 ascii 的時候將會失敗。

再來看看encode()和decode()兩個basestring的例項方法,理解了str和unicode的區別後,這兩個方法就不會再混淆了:

python3 renamed the unicode type to str ,the old str type has been replaced by bytes.

跟 python 2 類似,python 3 也有兩種型別,乙個是 unicode,乙個是 byte 碼。但是他們有不同的命名。

現在你從普通文字轉換成 「str」 型別後儲存的是乙個 unicode, 「bytes」 型別儲存的是 byte 串。你也可以通過乙個 b 字首來製造 byte 串。

python 3最重要的新特性大概要算是對文字和二進位制資料作了更為清晰的區分。文字總是unicode,由str型別表示,二進位制資料則由bytes型別表示。python 3不會以任意隱式的方式混用str和bytes,正是這使得兩者的區分特別清晰。你不能拼接字串和位元組包,也無法在位元組包裡搜尋字串(反之亦然),也不能將字串傳入引數為位元組包的函式(反之亦然)。這是件好事。

python 3 中對 unicode 支援的最大變化就是將會沒有對 byte 位元組串的自動解碼。如果你想要用乙個 byte 位元組串和乙個 unicode 相鏈結的話,你將會得到乙個錯誤,不管你包含的內容是什麼。

所有這些在 python 2 中都將會有隱式的處理,而在 python 3 中你將會得到乙個錯誤。

注意:無論py2,還是py3,與明文直接對應的就是unicode資料,列印unicode資料就會顯示相應的明文(包括英文和中文)

說到編碼,我們需要在全域性掌握這個工作過程,比如我們在pycharm上編寫乙個.py檔案,從儲存到執行資料到底是怎麼轉換的呢?

在解決這個問題之前,我們需要解決乙個問題:預設編碼

預設編碼

什麼是預設編碼?其實就是你的直譯器解釋**時預設的編碼方式,在py2裡預設的編碼方式是ascii,在py3裡則是utf8(sys.getdefaultencoding()檢視)。

1#-*- coding: utf-8 -*-

這個宣告是做什麼的?我們在最開始只知道在py2裡如果不加上這麼一句話,程式一旦出現中文就會報錯,其實就是因為py2預設的ascii碼,對於中文這些特殊字元無法編碼;

宣告這句話就是告訴python2.7直譯器 (預設acsii編碼方式)解釋hello.py檔案宣告下面的內容按utf8編碼,對,就是編碼(編碼成位元組串最後轉成0101的形式讓機器去執行) 

大家注意hello.py檔案儲存時有自己特定的編碼方式,比如utf8,比如gbk。

需要注意的是宣告的編碼必須與檔案實際儲存時用的編碼一致,否則很大機率會出現**解析異常。現在的ide一般會自動處理這種情況,改變宣告後同時換成宣告的編碼儲存,但文字編輯器控們需要小心。所以,儲存的編碼樣式取決於你的編輯器預設的樣式(可調)。

檔案儲存和執行過程

我們講過,字串在記憶體中是以unicode的資料形式儲存的,可什麼時候我們資料是在記憶體呢?讓我們一起解析這個過程

比如我們在pycharm上(py3.5)建立乙個hello.py檔案:

1print('hello 星星')

這個時候我們的資料在記憶體嗎?no,它已經被pycharm以預設的檔案儲存編碼方式存到了硬碟(二進位制資料),所以一定注意,你點選執行的時候,其實首先需要開啟這個檔案,然後將所有的資料轉移到記憶體,字串此時就以unicode的資料格式存到記憶體的某塊位址上(為什麼要這樣處理一會講到),其它內容還是utf8的編碼方式,然後直譯器就可以按著預設的utf8的編碼方式逐行解釋了。 

所以,一旦你的檔案儲存時的編碼與直譯器解釋的編碼不一致時就會出現錯誤。

1 cmd下的亂碼問題

hello.py

#coding:utf8

print ('星星')

檔案儲存時的編碼也為utf8。

思考:為什麼在ide下用2或3執行都沒問題,在cmd.exe下3正確,2亂碼呢?

我們在win下的終端即cmd.exe去執行,大家注意,cmd.exe本身就是乙個軟體;當我們python2 hello.py時,python2直譯器(預設ascii編碼)去按宣告的utf8編碼檔案,而檔案又是utf8儲存的,所以沒問題;問題出在當我們print'苑昊'時,直譯器這邊正常執行,也不會報錯,只是print的內容會傳遞給cmd.exe顯示,而在py2裡這個內容就是utf8編碼的位元組資料,而這個軟體預設的編碼解碼方式是gbk,所以cmd.exe用gbk的解碼方式去解碼utf8自然會亂碼。

py3正確的原因是傳遞給cmd的是unicode資料,符合iso統一標準的,所以沒問題。

1print(u'星星')

改成這樣後,cmd下用2也不會有問題了。 

2  print問題

在py2裡12

3#coding:utf8

print('星星')#星星

print(['星星','xing'])#['\xe8\x8b\x91\xe6\x98\x8a', 'xing']

在py3裡12

print('星星')#星星

print(['星星','xing'])#['星星', 'xing']

python3和python2的區別

1.效能 py3.0執行 pystone benchmark的速度比py2.5慢30 guido認為py3.0有極大的優化空間,在字串和整形操作上可 以取得很好的優化結果。py3.1效能比py2.5慢15 還有很大的提公升空間。2.編碼 py3.x原始碼檔案預設使用utf 8編碼,這就使得以下 是合...

Python2和Python3的比較

python2 python3 print fish print fish unicode 是單獨的 unicode utf 8 字串 b b china byte 和 bytearrays type b type bytes s b.decode 轉化成 string 型別b1 s encode ...

python3和python2的區別

這個星期開始學習python了,因為看的書都是基於python2.x,而且我安裝的是python3.1,所以書上寫的地方好多都不適用於python3.1,特意在google上search了一下3.x和2.x的區別。特此在自己的空間中記錄一下,以備以後查詢方便,也可以分享給想學習python的frie...