1. 程式人生 > >Python學習【第5篇】:Python之字元編碼問題 python之----------字元編碼具體原理

Python學習【第5篇】:Python之字元編碼問題 python之----------字元編碼具體原理

python之----------字元編碼具體原理

1.記憶體和硬碟都是用來儲存的。

CPU:速度快

硬碟:永久儲存

 

2.文字編輯器存取檔案的原理(nodepad++,pycharm,word)

   開啟編輯器就可以啟動一個程序,是在記憶體中的,所以在編輯器編寫的內容也都是存放在記憶體中的,斷電後資料就丟失了。因而需要儲存在硬碟上,點選儲存按鈕或快捷鍵,就把記憶體中的資料儲存到了硬碟上。在這一點上,我們編寫的py檔案(沒有執行時),跟編寫的其他檔案沒有什麼區別,都只是編寫一堆字元而已。

3.python直譯器執行py檔案的原理,例如python  test.py

  第一階段:python直譯器啟動,此時就相當於啟動了一個文字編輯器

  第二階段:python直譯器相當於文字編輯器,去開啟test.py,從硬碟上將test.py的檔案內容讀入到記憶體中

  第三階段:python直譯器執行剛剛載入到記憶體中的test.py的程式碼(在該階段,即執行時,才會識別python的語法,執行到字串時,會開闢記憶體空間存放字串)

總結:python直譯器與文字編輯器的異同

相同點:python直譯器是解釋執行檔案內容的,因而python直譯器具備讀py檔案的功能,這一點與文字編輯器一樣

不同點:文字編輯器將檔案內容讀入記憶體後,是為了顯示/編輯,而python直譯器將檔案內容讀入記憶體後,是為了執行(識別python的語法)

4.什麼是編碼?

  計算機想要工作必須通電,高低電平(高電平即二進位制數1,低電平即二進位制數0),也就是說計算機只認識數字。那麼讓計算機如何讀懂人類的字元呢?

  這就必須經過一個過程:

    字元---------(翻譯過程)-------------數字

  這個過程實際就是一個字元如何對應一個特定數字的標準,這個標準稱之為字元編碼。

5.以下兩個場景涉及到字元編碼的問題:

  1.一個python檔案中的內容是由一堆字元組成的(python檔案未執行時)

  2.python中的資料型別字串是由一串字元組成的(python檔案執行時)

6.字元編碼的發展史

階段一:現代計算機起源於美國,最早誕生也是基於英文考慮的ASCII

      ASCII:一個Bytes代表一個字元(英文字元/鍵盤上的所有其他字元),1Bytes=8bit,8bit可以表示0-2**8-1種變化,即可以表示256個字元

    ASCII最初只用了後七位,127個數字,已經完全能夠代表鍵盤上所有的字元了(英文字元/鍵盤的所有其他字元)

    後來為了將拉丁文也編碼進了ASCII表,將最高位也佔用了

階段二:為了滿足中文,中國人定製了GBK

  GBK:2Bytes代表一個字元,為了滿足其他國家,各個國家紛紛定製了自己的編碼,日本把日文編到Shift_JIS裡,韓國把韓文編到Euc-kr

階段三:各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文字中,顯示出來會有亂碼。

於是產生了unicode, 統一用2Bytes代表一個字元, 2**16-1=65535,可代表6萬多個字元,因而相容萬國語言

但對於通篇都是英文的文字來說,這種編碼方式無疑是多了一倍的儲存空間(二進位制最終都是以電或者磁的方式儲存到儲存介質中的)

於是產生了UTF-8,對英文字元只用1Bytes表示,對中文字元用3Bytes

需要強調的是:

  unicode:簡單粗暴,多有的字元都是2Bytes,優點是字元--數字的轉換速度快;缺點是佔用空間大。

  utf-8:精準,可變長,優點是節省空間;缺點是轉換速度慢,因為每次轉換都需要計算出需要多長Bytes才能夠準確表示。

1.記憶體中使用的編碼是unicode,用空間換時間(程式都需要載入到記憶體才能執行,因而記憶體應該是越快越好)

2.硬碟中或網路傳輸用utf-8,保證資料傳輸的穩定性。

1 所有程式,最終都要載入到記憶體,程式儲存到硬碟不同的國家用不同的編碼格式,但是到記憶體中我們為了相容萬國(計算機可以執行任何國家的程式原因在於此),統一且固定使用unicode,
2 這就是為何記憶體固定用unicode的原因,你可能會說相容萬國我可以用utf-8啊,可以,完全可以正常工作,之所以不用肯定是unicode比utf-8更高效啊(uicode固定用2個位元組編碼
3 ,utf-8則需要計算),但是unicode更浪費空間,沒錯,這就是用空間換時間的一種做法,而存放到硬碟,或者網路傳輸,都需要把unicode轉成utf-8,
4 因為資料的傳輸,追求的是穩定,高效,資料量越小資料傳輸就越靠譜,於是都轉成utf-8格式的,而不是unicode。

七、字元編碼轉換  

unicode------>encode(編碼)-------->utf-8

utf-8---------->decode--------->unicode

檔案從記憶體刷到硬碟的操作簡稱存檔案

檔案從硬碟讀到記憶體的操作簡稱讀檔案

亂碼:存檔案時就已經亂碼  或者  存檔案時不亂碼而讀檔案時亂碼

總結:

無論是何種編輯器,要防止檔案出現亂碼(請一定注意,存放一段程式碼的檔案也僅僅只是一個普通檔案而已,此處指的是檔案沒有執行前,我們開啟檔案時出現的亂碼)

核心法則就是,檔案以什麼編碼儲存的,就以什麼編碼方式開啟

 

八、 文字編輯器之python直譯器

檔案test.py以gbk格式儲存,內容為:

  x='林'

無論是

  python2 test.py

還是

  python3 test.py

都會報錯(因為python2預設ascii,python3預設utf-8)

除非在檔案開頭指定#coding:gbk

九、程式的執行

 python3 test.py  或 python2 test.py(執行test.py的第一步,一定是先將檔案內容讀入到記憶體中)

階段一:啟動python直譯器

階段二:python直譯器此時就是一個文字編輯器,負責開啟檔案test.py,即從硬碟中讀取test.py的內容到記憶體中

此時,python直譯器會讀取test.py 的第一行內容,#coding :utf-8,來決定以什麼編碼格式來讀入記憶體,這一行就是來設定python直譯器這個軟體的編碼使用的編碼格式這個編碼,python2預設使用ASCII,python3中預設使用utf-8

階段三:讀取已經載入到記憶體的程式碼(unicode編碼的二進位制),然後執行,執行過程中可能會開闢新的記憶體空間,比如x="egon"

 

記憶體的編碼使用unicode,不代表記憶體中全都是unicode編碼的二進位制,

 

在程式執行之前,記憶體中確實都是unicode編碼的二進位制,比如從檔案中讀取了一行x="egon",其中的x,等號,引號,地位都一樣,都是普通字元而已,都是以unicode編碼的二進位制形式存放與記憶體中的

 

但是程式在執行過程中,會申請記憶體(與程式程式碼所存在的記憶體是倆個空間),可以存放任意編碼格式的資料,比如x="egon",會被python直譯器識別為字串,會申請記憶體空間來存放"hello",然後讓x指向該記憶體地址,此時新申請的該記憶體地址儲存也是unicode編碼的egon,如果程式碼換成x="egon".encode('utf-8'),那麼新申請的記憶體空間裡存放的就是utf-8編碼的字串egon了

 

 十、python2與python3的區別

 

在python2中有兩種字串型別str和unicode

  在python2中,str就是編碼後的結果bytes,所以在Python2中,unicode字元編碼的結果就是str/bytes

 

複製程式碼
1 #coding:utf-8
2 s='林' #在執行時,'林'會被以conding:utf-8的形式儲存到新的記憶體空間中
3 
4 print repr(s) #'\xe6\x9e\x97' 三個Bytes,證明確實是utf-8
5 print type(s) #<type 'str'>
6 
7 s.decode('utf-8')
8 # s.encode('utf-8') #報錯,s為編碼後的結果bytes,所以只能decode
複製程式碼

  當python直譯器執行到產生字串的程式碼時(例如s=u'林'),會申請新的記憶體地址,然後將'林'以unicode的格式存放到新的記憶體空間中,所以s只能encode,不能decode

複製程式碼
1 s=u'林'
2 print repr(s) #u'\u6797'
3 print type(s) #<type 'unicode'>
4 
5 
6 # s.decode('utf-8') #報錯,s為unicode,所以只能encode
7 s.encode('utf-8') 
複製程式碼

對於unicode格式的資料來說,無論怎麼列印,都不會亂碼

python3中的字串與python2中的u'字串',都是unicode,所以無論如何列印都不會亂碼

在python3中也有兩種字串型別str和bytes\

  str是unicode

複製程式碼
1 #coding:utf-8
2 s='林' #當程式執行時,無需加u,'林'也會被以unicode形式儲存新的記憶體空間中,
3 
4 #s可以直接encode成任意編碼格式
5 s.encode('utf-8')
6 s.encode('gbk')
7 
8 print(type(s)) #<class 'str'>
複製程式碼

 

1.記憶體和硬碟都是用來儲存的。

CPU:速度快

硬碟:永久儲存

 

2.文字編輯器存取檔案的原理(nodepad++,pycharm,word)

   開啟編輯器就可以啟動一個程序,是在記憶體中的,所以在編輯器編寫的內容也都是存放在記憶體中的,斷電後資料就丟失了。因而需要儲存在硬碟上,點選儲存按鈕或快捷鍵,就把記憶體中的資料儲存到了硬碟上。在這一點上,我們編寫的py檔案(沒有執行時),跟編寫的其他檔案沒有什麼區別,都只是編寫一堆字元而已。

3.python直譯器執行py檔案的原理,例如python  test.py

  第一階段:python直譯器啟動,此時就相當於啟動了一個文字編輯器

  第二階段:python直譯器相當於文字編輯器,去開啟test.py,從硬碟上將test.py的檔案內容讀入到記憶體中

  第三階段:python直譯器執行剛剛載入到記憶體中的test.py的程式碼(在該階段,即執行時,才會識別python的語法,執行到字串時,會開闢記憶體空間存放字串)

總結:python直譯器與文字編輯器的異同

相同點:python直譯器是解釋執行檔案內容的,因而python直譯器具備讀py檔案的功能,這一點與文字編輯器一樣

不同點:文字編輯器將檔案內容讀入記憶體後,是為了顯示/編輯,而python直譯器將檔案內容讀入記憶體後,是為了執行(識別python的語法)

4.什麼是編碼?

  計算機想要工作必須通電,高低電平(高電平即二進位制數1,低電平即二進位制數0),也就是說計算機只認識數字。那麼讓計算機如何讀懂人類的字元呢?

  這就必須經過一個過程:

    字元---------(翻譯過程)-------------數字

  這個過程實際就是一個字元如何對應一個特定數字的標準,這個標準稱之為字元編碼。

5.以下兩個場景涉及到字元編碼的問題:

  1.一個python檔案中的內容是由一堆字元組成的(python檔案未執行時)

  2.python中的資料型別字串是由一串字元組成的(python檔案執行時)

6.字元編碼的發展史

階段一:現代計算機起源於美國,最早誕生也是基於英文考慮的ASCII

      ASCII:一個Bytes代表一個字元(英文字元/鍵盤上的所有其他字元),1Bytes=8bit,8bit可以表示0-2**8-1種變化,即可以表示256個字元

    ASCII最初只用了後七位,127個數字,已經完全能夠代表鍵盤上所有的字元了(英文字元/鍵盤的所有其他字元)

    後來為了將拉丁文也編碼進了ASCII表,將最高位也佔用了

階段二:為了滿足中文,中國人定製了GBK

  GBK:2Bytes代表一個字元,為了滿足其他國家,各個國家紛紛定製了自己的編碼,日本把日文編到Shift_JIS裡,韓國把韓文編到Euc-kr

階段三:各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文字中,顯示出來會有亂碼。

於是產生了unicode, 統一用2Bytes代表一個字元, 2**16-1=65535,可代表6萬多個字元,因而相容萬國語言

但對於通篇都是英文的文字來說,這種編碼方式無疑是多了一倍的儲存空間(二進位制最終都是以電或者磁的方式儲存到儲存介質中的)

於是產生了UTF-8,對英文字元只用1Bytes表示,對中文字元用3Bytes

需要強調的是:

  unicode:簡單粗暴,多有的字元都是2Bytes,優點是字元--數字的轉換速度快;缺點是佔用空間大。

  utf-8:精準,可變長,優點是節省空間;缺點是轉換速度慢,因為每次轉換都需要計算出需要多長Bytes才能夠準確表示。

1.記憶體中使用的編碼是unicode,用空間換時間(程式都需要載入到記憶體才能執行,因而記憶體應該是越快越好)

2.硬碟中或網路傳輸用utf-8,保證資料傳輸的穩定性。

1 所有程式,最終都要載入到記憶體,程式儲存到硬碟不同的國家用不同的編碼格式,但是到記憶體中我們為了相容萬國(計算機可以執行任何國家的程式原因在於此),統一且固定使用unicode,
2 這就是為何記憶體固定用unicode的原因,你可能會說相容萬國我可以用utf-8啊,可以,完全可以正常工作,之所以不用肯定是unicode比utf-8更高效啊(uicode固定用2個位元組編碼
3 ,utf-8則需要計算),但是unicode更浪費空間,沒錯,這就是用空間換時間的一種做法,而存放到硬碟,或者網路傳輸,都需要把unicode轉成utf-8,
4 因為資料的傳輸,追求的是穩定,高效,資料量越小資料傳輸就越靠譜,於是都轉成utf-8格式的,而不是unicode。

七、字元編碼轉換  

unicode------>encode(編碼)-------->utf-8

utf-8---------->decode--------->unicode

檔案從記憶體刷到硬碟的操作簡稱存檔案

檔案從硬碟讀到記憶體的操作簡稱讀檔案

亂碼:存檔案時就已經亂碼  或者  存檔案時不亂碼而讀檔案時亂碼

總結:

無論是何種編輯器,要防止檔案出現亂碼(請一定注意,存放一段程式碼的檔案也僅僅只是一個普通檔案而已,此處指的是檔案沒有執行前,我們開啟檔案時出現的亂碼)

核心法則就是,檔案以什麼編碼儲存的,就以什麼編碼方式開啟

 

八、 文字編輯器之python直譯器

檔案test.py以gbk格式儲存,內容為:

  x='林'

無論是

  python2 test.py

還是

  python3 test.py

都會報錯(因為python2預設ascii,python3預設utf-8)

除非在檔案開頭指定#coding:gbk

九、程式的執行

 python3 test.py  或 python2 test.py(執行test.py的第一步,一定是先將檔案內容讀入到記憶體中)

階段一:啟動python直譯器

階段二:python直譯器此時就是一個文字編輯器,負責開啟檔案test.py,即從硬碟中讀取test.py的內容到記憶體中

此時,python直譯器會讀取test.py 的第一行內容,#coding :utf-8,來決定以什麼編碼格式來讀入記憶體,這一行就是來設定python直譯器這個軟體的編碼使用的編碼格式這個編碼,python2預設使用ASCII,python3中預設使用utf-8

階段三:讀取已經載入到記憶體的程式碼(unicode編碼的二進位制),然後執行,執行過程中可能會開闢新的記憶體空間,比如x="egon"

 

記憶體的編碼使用unicode,不代表記憶體中全都是unicode編碼的二進位制,

 

在程式執行之前,記憶體中確實都是unicode編碼的二進位制,比如從檔案中讀取了一行x="egon",其中的x,等號,引號,地位都一樣,都是普通字元而已,都是以unicode編碼的二進位制形式存放與記憶體中的

 

但是程式在執行過程中,會申請記憶體(與程式程式碼所存在的記憶體是倆個空間),可以存放任意編碼格式的資料,比如x="egon",會被python直譯器識別為字串,會申請記憶體空間來存放"hello",然後讓x指向該記憶體地址,此時新申請的該記憶體地址儲存也是unicode編碼的egon,如果程式碼換成x="egon".encode('utf-8'),那麼新申請的記憶體空間裡存放的就是utf-8編碼的字串egon了

 

 十、python2與python3的區別

 

在python2中有兩種字串型別str和unicode

  在python2中,str就是編碼後的結果bytes,所以在Python2中,unicode字元編碼的結果就是str/bytes

 

複製程式碼
1 #coding:utf-8
2 s='林' #在執行時,'林'會被以conding:utf-8的形式儲存到新的記憶體空間中
3 
4 print repr(s) #'\xe6\x9e\x97' 三個Bytes,證明確實是utf-8
5 print type(s) #<type 'str'>
6 
7 s.decode('utf-8')
8 # s.encode('utf-8') #報錯,s為編碼後的結果bytes,所以只能decode
複製程式碼

  當python直譯器執行到產生字串的程式碼時(例如s=u'林'),會申請新的記憶體地址,然後將'林'以unicode的格式存放到新的記憶體空間中,所以s只能encode,不能decode

複製程式碼
1 s=u'林'
2 print repr(s) #u'\u6797'
3 print type(s) #<type 'unicode'>
4 
5 
6 # s.decode('utf-8') #報錯,s為unicode,所以只能encode
7 s.encode('utf-8') 
複製程式碼

對於unicode格式的資料來說,無論怎麼列印,都不會亂碼

python3中的字串與python2中的u'字串',都是unicode,所以無論如何列印都不會亂碼

在python3中也有兩種字串型別str和bytes\

  str是unicode

複製程式碼
1 #coding:utf-8
2 s='林' #當程式執行時,無需加u,'林'也會被以unicode形式儲存新的記憶體空間中,
3 
4 #s可以直接encode成任意編碼格式
5 s.encode('utf-8')
6 s.encode('gbk')
7 
8 print(type(s)) #<class 'str'>
複製程式碼