Python字符編碼

 一、內存和硬盤都是用來存儲的node

  內存:速度快python

  硬盤:永久保存網絡

二、文本編輯器存取文件的原理(nodepad++,pycharm,word)編輯器

   打開編輯器就能夠啓動一個進程,是在內存中的,因此在編輯器編寫的內容也都是存放在內存中的,斷電後數據就丟失了。於是須要保存在硬盤上,點擊保存按鈕或快捷鍵,就把內存中的數據保存到了硬盤上。在這一點上,咱們編寫的py文件(沒有執行時),跟編寫的其餘文件沒有什麼區別,都只是編寫一堆字符而已。ide

三、Python解釋器執行py文件的原理,例如 python test.py編碼

  第一階段:啓動Python解釋器,這就至關於啓動了一個文本編輯器spa

  第二階段:將硬盤上的test.py文件看成文本文件讀入內存翻譯

  第三階段:Python解釋器執行剛剛加載到內存中的 test.py 的代碼(在該階段,即執行時,纔會識別Python的語法,執行到字符串時,會開闢內存空間存放字符串)code

總結:Python解釋器與文本編輯器的異同blog

相同點:Python解釋器是解釋執行文件內容的,於是Python解釋器具有讀py文件的功能,這一點與文本編輯器同樣

不一樣點:文本編輯器將文件內容讀入內存後,是爲了顯示/編輯,而python解釋器將文件內容讀入內存後,是爲了執行(識別python的語法)

四、什麼是字符編碼

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

  這就必須通過一個過程:

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

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

五、如下兩個場景涉及到字符編碼的問題:

  1)一個Python文件中的內容是由一堆字符組成的(Python文件未執行時)

  2)Python中的數據類型字符串是由一串字符組成的(Python文件執行時)

六、字符編碼的發展史

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

  ASCII碼:只能識別英文字符,一個字節(Bytes)表明一個英文字符或鍵盤上的全部其餘字符,1Bytes = 8bit(比特位),8bit 能夠表示 0 —— (2^8-1) 種變化,便可以表示256個字符。

階段二:爲了知足中文,中國人定製了GBK

  GBK:2Bytes表明一個字符,爲了知足其餘國家,各個國家紛紛定製了本身的編碼,日本把日文編到Shift_JIS裏,韓國把韓文編到Euc-kr裏。

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

  統一用 2Bytes 表明一個字符,2^16-1=65535,可表明6萬多個字符,於是兼容萬國語言

  但對於通篇都是英文的文原本說,這種編碼方式無疑是多了一倍的存儲空間,因而產生了UTF-8,對英文字符只用 1Bytes 表示,對中文字符用 3Bytes。

須要強調的是:

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

  UTF-8:精準,可變長,優勢是節省空間;缺點是轉換速度慢,由於每次轉換都須要計算出須要多長Bytes纔可以準確表示。

一、內存中使用的編碼是Unicode,用空間換時間(程序都須要加載到內存才能運行,於是內存應該是越快越好)

二、硬盤中或網絡傳輸用UTF-8,保證數據傳輸的穩定性。

全部程序,最終都要加載到內存,程序保存到硬盤,不一樣的國家用不一樣的編碼格式,可是到內存中咱們爲了兼容萬國(計算機能夠運行任何國家的程序緣由就在於此),統一且固定使用Unicode 這就是爲什麼內存固定用Unicode的緣由,你可能會說兼容萬國我能夠用UTF-8啊,能夠,徹底能夠正常工做,之因此不用確定是Unicode比UTF-8更高效(Unicode固定用2個字節編碼,UTF-8則須要計算),可是Unicode更浪費空間,沒錯,這就是用空間換時間的一種作法,而存放到硬盤,或者網絡傳輸,都須要把Unicode轉成UTF-8,由於數據的傳輸,追求的是穩定,高效,數據量越小數據傳輸就越靠譜,因而都轉成UTF-8格式的,而不是Unicode。
爲何內存使用Unicode不使用UTF-8

七、字符編碼轉換

字符 --- 編碼 --> Unicode的二進制 ------- 編碼 -----> GBK的二進制

GBK的二進制 ----- 解碼 --> unicode的二進制 ---- 解碼 --> 字符

文件從內存刷到硬盤的操做簡稱存文件

文件從硬盤讀到內存的操做簡稱讀文件

亂碼:存文件時就已經亂碼  或者  存文件時不亂碼而讀文件時亂碼

總結:不管是何種編輯器,要防止文件出現亂碼(請必定注意,存放一段代碼的文件也僅僅只是一個普通文件而已,此處指的是文件沒有執行前,咱們打開文件時出現的亂碼)

核心法則就是,字符用什麼編碼格式編碼的,就應該用什麼編碼格式進行解碼

八、 Python解釋器默認的字符編碼

例:文件 test.py 以 gbk 格式保存,內容爲:

  x = '湫'

不管是python2 test.py,仍是python3 test.py,都會報錯,由於解釋器默認的字符編碼:

  Python2:ASCII

  Python3:UTF-8

經過文件頭能夠修改Python解釋器默認使用的字符編碼,在文件首行寫:#coding: 後面跟上文件當初存的時候用的字符編碼

九、程序的執行

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 = "qiuxi"

注意:

  內存的編碼使用Unicode,不表明內存中全都是Unicode編碼的二進制

  在程序執行以前,內存中確實都是Unicode編碼的二進制,好比從文件中讀取了一行 x = "qiuxi",其中的x,賦值號,引號,地位都同樣,都是普通字符而已,都是以Unicode編碼的二進制形式存放於內存中的,可是程序在執行過程當中,會申請內存(與程序代碼所存在的內存是兩個空間),能夠存聽任意編碼格式的數據,好比x = "qiuxi",會被Python解釋器識別爲字符串,會申請內存空間來存放"qiuxi",而後讓 x 指向該內存地址,此時新申請的內存地址保存的也是Unicode編碼的qiuxi,若是代碼換成 x = "qiuxi".encode('utf-8'),那麼新申請的內存空間裏存放的就是UTF-8編碼的字符串qiuxi了

十、Python2與Python3的區別

在Python2中有兩種字符串相關類型:str 和 Unicode

# -*- coding: utf-8 -*-
s = '' # 在執行時,'林'會被utf-8的形式保存到新的內存空間中

print repr(s) # '\xe6\x9e\x97' 三個Bytes,證實確實是utf-8
print type(s) # <type 'str'>
 s.decode('utf-8') # s.encode('utf-8') # 報錯,s爲編碼後的結果bytes,因此只能decode

當Python解釋器執行到產生字符串的代碼時(例如s = u'林'),會申請新的內存地址,而後將 '林' 以Unicode的格式存放到新的內存空間中,因此 s 只能encode,不能decode

s = u''
print repr(s) # u'\u6797'
print type(s) # <type 'unicode'>

# s.decode('utf-8') # 報錯,s爲Unicode,因此只能encode
s.encode('utf-8')

對於unicode格式的數據來講,不管怎麼打印,都不會亂碼

Python3中的字符串與Python2中的u'字符串',都是Unicode,因此不管如何打印都不會亂碼

在python3中也有兩種字符串相關類型:str 和 bytes

  str是Unicode

# -*- coding: utf-8 -*-
s = '' # 當程序執行時,無需加u,'林'也會被以Unicode形式保存新的內存空間中,

# s能夠直接encode成任意編碼格式
s.encode('utf-8') s.encode('gbk') print(type(s)) # <class 'str'>
相關文章
相關標籤/搜索