python基础之字符编码
閱讀目錄
- 一 了解字符編碼的知識(shí)儲(chǔ)備
- 二 字符編碼介紹
- 三 字符編碼應(yīng)用之文件編輯器
- 3.1 文本編輯器之nodpad++
- 3.2 文本編輯器之pycharm
- 3.3 文本編輯器之python解釋器
- 3.4 總結(jié)
- 四 字符編碼應(yīng)用之python
- 4.1 執(zhí)行python程序的三個(gè)階段
- 4.2 python2與python3字符串類型的區(qū)別
一 了解字符編碼的知識(shí)儲(chǔ)備
一 計(jì)算機(jī)基礎(chǔ)知識(shí)
?
二 文本編輯器存取文件的原理(nodepad++,pycharm,word)
#1、打開編輯器就打開了啟動(dòng)了一個(gè)進(jìn)程,是在內(nèi)存中的,所以,用編輯器編寫的內(nèi)容也都是存放與內(nèi)存中的,斷電后數(shù)據(jù)丟失#2、要想永久保存,需要點(diǎn)擊保存按鈕:編輯器把內(nèi)存的數(shù)據(jù)刷到了硬盤上。#3、在我們編寫一個(gè)py文件(沒有執(zhí)行),跟編寫其他文件沒有任何區(qū)別,都只是在編寫一堆字符而已。三 python解釋器執(zhí)行py文件的原理 ,例如python test.py
#第一階段:python解釋器啟動(dòng),此時(shí)就相當(dāng)于啟動(dòng)了一個(gè)文本編輯器#第二階段:python解釋器相當(dāng)于文本編輯器,去打開test.py文件,從硬盤上將test.py的文件內(nèi)容讀入到內(nèi)存中(小復(fù)習(xí):pyhon的解釋性,決定了解釋器只關(guān)心文件內(nèi)容,不關(guān)心文件后綴名)#第三階段:python解釋器解釋執(zhí)行剛剛加載到內(nèi)存中test.py的代碼( ps:在該階段,即真正執(zhí)行代碼時(shí),才會(huì)識(shí)別python的語(yǔ)法,執(zhí)行文件內(nèi)代碼,當(dāng)執(zhí)行到name="egon"時(shí),會(huì)開辟內(nèi)存空間存放字符串"egon")四?總結(jié)python解釋器與文件本編輯的異同
#1、相同點(diǎn):python解釋器是解釋執(zhí)行文件內(nèi)容的,因而python解釋器具備讀py文件的功能,這一點(diǎn)與文本編輯器一樣#2、不同點(diǎn):文本編輯器將文件內(nèi)容讀入內(nèi)存后,是為了顯示或者編輯,根本不去理會(huì)python的語(yǔ)法,而python解釋器將文件內(nèi)容讀入內(nèi)存后,可不是為了給你瞅一眼python代碼寫的啥,而是為了執(zhí)行python代碼、會(huì)識(shí)別python語(yǔ)法。二 字符編碼介紹
一 什么是字符編碼
計(jì)算機(jī)要想工作必須通電,即用‘電’驅(qū)使計(jì)算機(jī)干活,也就是說(shuō)‘電’的特性決定了計(jì)算機(jī)的特性。電的特性即高低電平(人類從邏輯上將二進(jìn)制數(shù)1對(duì)應(yīng)高電平,二進(jìn)制數(shù)0對(duì)應(yīng)低電平),關(guān)于磁盤的磁特性也是同樣的道理。結(jié)論:計(jì)算機(jī)只認(rèn)識(shí)數(shù)字很明顯,我們平時(shí)在使用計(jì)算機(jī)時(shí),用的都是人類能讀懂的字符(用高級(jí)語(yǔ)言編程的結(jié)果也無(wú)非是在文件內(nèi)寫了一堆字符),如何能讓計(jì)算機(jī)讀懂人類的字符?必須經(jīng)過(guò)一個(gè)過(guò)程:#字符--------(翻譯過(guò)程)------->數(shù)字 #這個(gè)過(guò)程實(shí)際就是一個(gè)字符如何對(duì)應(yīng)一個(gè)特定數(shù)字的標(biāo)準(zhǔn),這個(gè)標(biāo)準(zhǔn)稱之為字符編碼二?以下兩個(gè)場(chǎng)景下涉及到字符編碼的問(wèn)題:
#1、一個(gè)python文件中的內(nèi)容是由一堆字符組成的,存取均涉及到字符編碼問(wèn)題(python文件并未執(zhí)行,前兩個(gè)階段均屬于該范疇)#2、python中的數(shù)據(jù)類型字符串是由一串字符組成的(python文件執(zhí)行時(shí),即第三個(gè)階段)三 字符編碼的發(fā)展史與分類(了解)
計(jì)算機(jī)由美國(guó)人發(fā)明,最早的字符編碼為ASCII,只規(guī)定了英文字母數(shù)字和一些特殊字符與數(shù)字的對(duì)應(yīng)關(guān)系。最多只能用 8 位來(lái)表示(一個(gè)字節(jié)),即:2**8 = 256,所以,ASCII碼最多只能表示 256 個(gè)符號(hào)
當(dāng)然我們編程語(yǔ)言都用英文沒問(wèn)題,ASCII夠用,但是在處理數(shù)據(jù)時(shí),不同的國(guó)家有不同的語(yǔ)言,日本人會(huì)在自己的程序中加入日文,中國(guó)人會(huì)加入中文。
而要表示中文,單拿一個(gè)字節(jié)表表示一個(gè)漢子,是不可能表達(dá)完的(連小學(xué)生都認(rèn)識(shí)兩千多個(gè)漢字),解決方法只有一個(gè),就是一個(gè)字節(jié)用>8位2進(jìn)制代表,位數(shù)越多,代表的變化就多,這樣,就可以盡可能多的表達(dá)出不通的漢字
所以中國(guó)人規(guī)定了自己的標(biāo)準(zhǔn)gb2312編碼,規(guī)定了包含中文在內(nèi)的字符->數(shù)字的對(duì)應(yīng)關(guān)系。
日本人規(guī)定了自己的Shift_JIS編碼
韓國(guó)人規(guī)定了自己的Euc-kr編碼(另外,韓國(guó)人說(shuō),計(jì)算機(jī)是他們發(fā)明的,要求世界統(tǒng)一用韓國(guó)編碼,但世界人民沒有搭理他們)
?
這時(shí)候問(wèn)題出現(xiàn)了,精通18國(guó)語(yǔ)言的小周同學(xué)謙虛的用8國(guó)語(yǔ)言寫了一篇文檔,那么這篇文檔,按照哪國(guó)的標(biāo)準(zhǔn),都會(huì)出現(xiàn)亂碼(因?yàn)榇丝痰母鞣N標(biāo)準(zhǔn)都只是規(guī)定了自己國(guó)家的文字在內(nèi)的字符跟數(shù)字的對(duì)應(yīng)關(guān)系,如果單純采用一種國(guó)家的編碼格式,那么其余國(guó)家語(yǔ)言的文字在解析時(shí)就會(huì)出現(xiàn)亂碼)
所以迫切需要一個(gè)世界的標(biāo)準(zhǔn)(能包含全世界的語(yǔ)言)于是unicode應(yīng)運(yùn)而生(韓國(guó)人表示不服,然后沒有什么卵用)
ascii用1個(gè)字節(jié)(8位二進(jìn)制)代表一個(gè)字符
unicode常用2個(gè)字節(jié)(16位二進(jìn)制)代表一個(gè)字符,生僻字需要用4個(gè)字節(jié)
例:
字母x,用ascii表示是十進(jìn)制的120,二進(jìn)制0111 1000
漢字中已經(jīng)超出了ASCII編碼的范圍,用Unicode編碼是十進(jìn)制的20013,二進(jìn)制的01001110 00101101。
字母x,用unicode表示二進(jìn)制0000 0000 0111 1000,所以u(píng)nicode兼容ascii,也兼容萬(wàn)國(guó),是世界的標(biāo)準(zhǔn)
?
這時(shí)候亂碼問(wèn)題消失了,所有的文檔我們都使用但是新問(wèn)題出現(xiàn)了,如果我們的文檔通篇都是英文,你用unicode會(huì)比ascii耗費(fèi)多一倍的空間,在存儲(chǔ)和傳輸上十分的低效
本著節(jié)約的精神,又出現(xiàn)了把Unicode編碼轉(zhuǎn)化為“可變長(zhǎng)編碼”的UTF-8編碼。UTF-8編碼把一個(gè)Unicode字符根據(jù)不同的數(shù)字大小編碼成1-6個(gè)字節(jié),常用的英文字母被編碼成1個(gè)字節(jié),漢字通常是3個(gè)字節(jié),只有很生僻的字符才會(huì)被編碼成4-6個(gè)字節(jié)。如果你要傳輸?shù)奈谋景罅坑⑽淖址?#xff0c;用UTF-8編碼就能節(jié)省空間:
| A | 01000001 | 00000000 01000001 | 01000001 |
| 中 | x | 01001110 00101101 | 11100100 10111000 10101101 |
從上面的表格還可以發(fā)現(xiàn),UTF-8編碼有一個(gè)額外的好處,就是ASCII編碼實(shí)際上可以被看成是UTF-8編碼的一部分,所以,大量只支持ASCII編碼的歷史遺留軟件可以在UTF-8編碼下繼續(xù)工作。
四 總結(jié)字符編碼的發(fā)展可分為三個(gè)階段(重要)
?!!!重點(diǎn)!!!三 字符編碼應(yīng)用之文件編輯器
3.1 文本編輯器之nodpad++
?
?!!!亂碼分析!!!?3.2 文本編輯器之pycharm
以u(píng)tf-8格式打開(選擇reload)
?pycharm中:reload與convert的區(qū)別3.3 文本編輯器之python解釋器
文件test.py以gbk格式保存,內(nèi)容為:x='林'無(wú)論是python2 test.py還是python3 test.py都會(huì)報(bào)錯(cuò)(因?yàn)閜ython2默認(rèn)ascii,python3默認(rèn)utf-8)除非在文件開頭指定#coding:gbk3.4 總結(jié)
!!!總結(jié)非常重要的兩點(diǎn)!!!
#1、保證不亂嗎的核心法則就是,字符按照什么標(biāo)準(zhǔn)而編碼的,就要按照什么標(biāo)準(zhǔn)解碼,此處的標(biāo)準(zhǔn)指的就是字符編碼#2、在內(nèi)存中寫的所有字符,一視同仁,都是unicode編碼,比如我們打開編輯器,輸入一個(gè)“你”,我們并不能說(shuō)“你”就是一個(gè)漢字,此時(shí)它僅僅只是一個(gè)符號(hào),該符號(hào)可能很多國(guó)家都在使用,根據(jù)我們使用的輸入法不同這個(gè)字的樣式可能也不太一樣。只有在我們往硬盤保存或者基于網(wǎng)絡(luò)傳輸時(shí),才能確定”你“到底是一個(gè)漢字,還是一個(gè)日本字,這就是unicode轉(zhuǎn)換成其他編碼格式的過(guò)程了? ? ? ? ? ? ? ? ? unicode----->encode-------->utf-8
? ? ? ? ? ? ? ? ? utf-8-------->decode---------->unicode
#補(bǔ)充:瀏覽網(wǎng)頁(yè)的時(shí)候,服務(wù)器會(huì)把動(dòng)態(tài)生成的Unicode內(nèi)容轉(zhuǎn)換為UTF-8再傳輸?shù)綖g覽器如果服務(wù)端encode的編碼格式是utf-8, 客戶端內(nèi)存中收到的也是utf-8編碼的結(jié)果。?
四 字符編碼應(yīng)用之python
4.1 執(zhí)行python程序的三個(gè)階段
python test.py ? (我再?gòu)?qiáng)調(diào)一遍,執(zhí)行test.py的第一步,一定是先將文件內(nèi)容讀入到內(nèi)存中)
test.py文件內(nèi)容以gbk格式保存的,內(nèi)容為:
階段一:啟動(dòng)python解釋器
階段二:python解釋器此時(shí)就是一個(gè)文本編輯器,負(fù)責(zé)打開文件test.py,即從硬盤中讀取test.py的內(nèi)容到內(nèi)存中
此時(shí),python解釋器會(huì)讀取test.py的第一行內(nèi)容,#coding:utf-8,來(lái)決定以什么編碼格式來(lái)讀入內(nèi)存,這一行就是來(lái)設(shè)定python解釋器這個(gè)軟件的編碼使用的編碼格式這個(gè)編碼,可以用sys.getdefaultencoding()查看,如果不在python文件指定頭信息#-*-coding:utf-8-*-,那就使用默認(rèn)的python2中默認(rèn)使用ascii,python3中默認(rèn)使用utf-8??
改正:在test.py指定文件頭,字符編碼一定要為gbk,
#coding:gbk 你好啊階段三:讀取已經(jīng)加載到內(nèi)存的代碼(unicode編碼格式),然后執(zhí)行,執(zhí)行過(guò)程中可能會(huì)開辟新的內(nèi)存空間,比如x="egon"
內(nèi)存的編碼使用unicode,不代表內(nèi)存中全都是unicode,在程序執(zhí)行之前,內(nèi)存中確實(shí)都是unicode,比如從文件中讀取了一行x="egon",其中的x,等號(hào),引號(hào),地位都一樣,都是普通字符而已,都是以u(píng)nicode的格式存放于內(nèi)存中的但是程序在執(zhí)行過(guò)程中,會(huì)申請(qǐng)內(nèi)存(與程序代碼所存在的內(nèi)存是倆個(gè)空間)用來(lái)存放python的數(shù)據(jù)類型的值,而python的字符串類型又涉及到了字符的概念比如x="egon",會(huì)被python解釋器識(shí)別為字符串,會(huì)申請(qǐng)內(nèi)存空間來(lái)存放字符串類型的值,至于該字符串類型的值被識(shí)別成何種編碼存放,這就與python解釋器的有關(guān)了,而python2與python3的字符串類型又有所不同。4.2 python2與python3字符串類型的區(qū)別
一 在python2中有兩種字符串類型str和unicode
str類型
當(dāng)python解釋器執(zhí)行到產(chǎn)生字符串的代碼時(shí)(例如x='上'),會(huì)申請(qǐng)新的內(nèi)存地址,然后將'上'編碼成文件開頭指定的編碼格式
要想看x在內(nèi)存中的真實(shí)格式,可以將其放入列表中再打印,而不要直接打印,因?yàn)橹苯觩rint()會(huì)自動(dòng)轉(zhuǎn)換編碼,這一點(diǎn)我們稍后再說(shuō)。
#coding:gbk x='上' y='下' print([x,y]) #['\xc9\xcf', '\xcf\xc2'] #\x代表16進(jìn)制,此處是c9cf總共4位16進(jìn)制數(shù),一個(gè)16進(jìn)制四4個(gè)比特位,4個(gè)16進(jìn)制數(shù)則是16個(gè)比特位,即2個(gè)Bytes,這就證明了按照gbk編碼中文用2Bytes print(type(x),type(y)) #(<type 'str'>, <type 'str'>)理解字符編碼的關(guān)鍵!!!
內(nèi)存中的數(shù)據(jù)通常用16進(jìn)制表示,2位16進(jìn)制數(shù)據(jù)代表一個(gè)字節(jié),如\xc9,代表兩位16進(jìn)制,一個(gè)字節(jié)
gbk存中文需要2個(gè)bytes,而存英文則需要1個(gè)bytes,它是如何做到的???!!!
gbk會(huì)在每個(gè)bytes,即8位bit的第一個(gè)位作為標(biāo)志位,標(biāo)志位為1則表示是中文字符,如果標(biāo)志位為0則表示為英文字符
x=‘你a好’ 轉(zhuǎn)成gbk格式二進(jìn)制位 8bit+8bit+8bit+8bit+8bit=(1+7bit)+(1+7bit)+(0+7bit)+(1+7bit)+(1+7bit)這樣計(jì)算機(jī)按照從左往右的順序讀:
#連續(xù)讀到前兩個(gè)括號(hào)內(nèi)的首位標(biāo)志位均為1,則構(gòu)成一個(gè)中午字符:你#讀到第三個(gè)括號(hào)的首位標(biāo)志為0,則該8bit代表一個(gè)英文字符:a#連續(xù)讀到后兩個(gè)括號(hào)內(nèi)的首位標(biāo)志位均為1,則構(gòu)成一個(gè)中午字符:好也就是說(shuō),每個(gè)Bytes留給我們用來(lái)存真正值的有效位數(shù)只有7位,而在unicode表中存放的只是這有效的7位,至于首位的標(biāo)志位與具體的編碼有關(guān),即在unicode中表示gbk的方式為:
(7bit)+(7bit)+(7bit)+(7bit)+(7bit)?
按照上圖翻譯的結(jié)果,我們可以去unicode關(guān)于漢字的對(duì)應(yīng)關(guān)系中去查:鏈接:https://pan.baidu.com/s/1dEV3RYp
?
可以看到“”上“”對(duì)應(yīng)的gbk(G0代表的是gbk)編碼就為494F,即我們得出的結(jié)果,而上對(duì)應(yīng)的unicode編碼為4E0A,我們可以將gbk-->decode-->unicode
#coding:gbk x='上'.decode('gbk') y='下'.decode('gbk') print([x,y]) #[u'\u4e0a', u'\u4e0b']unicode類型
當(dāng)python解釋器執(zhí)行到產(chǎn)生字符串的代碼時(shí)(例如s=u'林'),會(huì)申請(qǐng)新的內(nèi)存地址,然后將'林'以u(píng)nicode的格式存放到新的內(nèi)存空間中,所以s只能encode,不能decode
#coding:gbk x=u'上' #等同于 x='上'.decode('gbk') y=u'下' #等同于 y='下'.decode('gbk') print([x,y]) #[u'\u4e0a', u'\u4e0b'] print(type(x),type(y)) #(<type 'unicode'>, <type 'unicode'>)打印到終端
對(duì)于print需要特別說(shuō)明的是:
當(dāng)程序執(zhí)行時(shí),比如
x='上' #gbk下,字符串存放為\xc9\xcf
print(x) #這一步是將x指向的那塊新的內(nèi)存空間(非代碼所在的內(nèi)存空間)中的內(nèi)存,打印到終端,按理說(shuō)應(yīng)該是存的什么就打印什么,但打印\xc9\xcf,對(duì)一些不熟知python編碼的程序員,立馬就懵逼了,所以龜叔自作主張,在print(x)時(shí),使用終端的編碼格式,將內(nèi)存中的\xc9\xcf轉(zhuǎn)成字符顯示,此時(shí)就需要終端編碼必須為gbk,否則無(wú)法正常顯示原內(nèi)容:上
對(duì)于unicode格式的數(shù)據(jù)來(lái)說(shuō),無(wú)論怎么打印,都不會(huì)亂碼
unicode這么好,不會(huì)亂碼,那python2為何還那么別扭,搞一個(gè)str出來(lái)呢?python誕生之時(shí),unicode并未像今天這樣普及,很明顯,好的東西你能看得見,龜叔早就看見了,龜叔在python3中將str直接存成unicode,我們定義一個(gè)str,無(wú)需加u前綴,就是一個(gè)unicode,屌不屌?
?
二 在python3 中也有兩種字符串類型str和bytes
str是unicode
#coding:gbk x='上' #當(dāng)程序執(zhí)行時(shí),無(wú)需加u,'上'也會(huì)被以u(píng)nicode形式保存新的內(nèi)存空間中,print(type(x)) #<class 'str'>#x可以直接encode成任意編碼格式 print(x.encode('gbk')) #b'\xc9\xcf' print(type(x.encode('gbk'))) #<class 'bytes'>很重要的一點(diǎn)是:看到python3中x.encode('gbk') 的結(jié)果\xc9\xcf正是python2中的str類型的值,而在python3是bytes類型,在python2中則是str類型
于是我有一個(gè)大膽的推測(cè):python2中的str類型就是python3的bytes類型,于是我查看python2的str()源碼,發(fā)現(xiàn)
轉(zhuǎn)載于:https://www.cnblogs.com/iamjianghao/p/8028890.html
總結(jié)
以上是生活随笔為你收集整理的python基础之字符编码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java编程石头剪刀布_java 开发的
- 下一篇: python函数的作用降低编程复杂度_P