Python之字符串和編碼

字符編碼

字符串相對于其他數(shù)據(jù)類型有一個特殊的地方:就是編碼問題。
我們知道計算機只能處理數(shù)字般婆,所以要讓它能夠處理文本就需要將文本用對應的數(shù)字來表示才能處理。所以美國人一開始設(shè)計出了ASCII編碼朵逝,只有127個字符被編碼到計算機里蔚袍,也就是大小寫英文字母、數(shù)字和一些符號配名。但是用一個字節(jié)來處理中文遠遠不夠啤咽,至少需要兩個字節(jié),中國人只好自己制定了GB2312編碼來處理漢字渠脉。由于GB2312編碼能夠處理的漢字也有限宇整,微軟又在GB2312編碼基礎(chǔ)上制定GBK編碼。隨后中國制定出了GB10803編碼连舍,與GB2312完全兼容,與GBK基本兼容涩哟,支持Unicode的全部統(tǒng)一漢字索赏,共收錄漢字70244個。GB 18030主要有以下特點:

  • 與UTF-8相同贴彼,采用多字節(jié)編碼潜腻,每個字可以由1個、2個或4個字節(jié)組成器仗。
  • 編碼空間龐大融涣,最多可定義161萬個字符。
  • 支持中國國內(nèi)少數(shù)民族的文字精钮,不需要動用造字區(qū)威鹿。
  • 漢字收錄范圍包含繁體漢字以及日韓漢字。

像天朝一樣轨香,當計算機傳到世界各個國家時忽你,為了適合當?shù)卣Z言和字符,設(shè)計和實現(xiàn)類似GB2312/GBK/GB18030的編碼方案臂容。這樣各搞一套科雳,在本地使用沒有問題根蟹,一旦出現(xiàn)在網(wǎng)絡(luò)中,由于不兼容糟秘,互相訪問就出現(xiàn)了亂碼現(xiàn)象简逮。 為了能夠處理各國的文字,由此Unicode(萬國碼尿赚,統(tǒng)一碼散庶,單一碼,標準萬國碼)編碼應運而生吼畏,Unicode編碼系統(tǒng)為表達任意語言的任意字符而設(shè)計督赤。它使用4字節(jié)的數(shù)字來表達每個字母、符號泻蚊,或者表意文字躲舌。
統(tǒng)一成Unicode編碼,亂碼問題從此消失了性雄。但是没卸,如果你寫的文本基本上全部是英文的話,用Unicode編碼比ASCII編碼需要多一倍的存儲空間秒旋,在存儲和傳輸上就十分不劃算约计。人們又想出了把Unicode編碼轉(zhuǎn)化為“可變長編碼”的UTF-8編碼。
UTF-8使用一至四個字節(jié)為每個字符編碼迁筛,UTF-8是ASCII的一個超集煤蚌。因為一個純ASCII字符串也是一個合法的UTF-8字符串,所以現(xiàn)存的ASCII文本不需要轉(zhuǎn)換细卧。

Python字符串

幾個常用關(guān)于字符串的函數(shù):

  • ord():獲取字符的整數(shù)表示尉桩。
>>> ord('b')
98
>>> ord('字')
23383
  • chr():把編碼轉(zhuǎn)換為對應的字符。
>>> chr(99)
'c'
>>> chr(23384)
'存'
  • encode():將字符串編碼為指定的bytes贪庙。
encode()函數(shù).png

純英文的str可以用ASCII編碼為bytes蜘犁,內(nèi)容是一樣的,含有中文的str可以用UTF-8編碼為bytes止邮。含有中文的str無法用ASCII編碼这橙,因為中文編碼的范圍超過了ASCII編碼的范圍,Python會報錯导披。在bytes中屈扎,無法顯示為ASCII字符的字節(jié),用\x##顯示撩匕。

  • decode():若我們從網(wǎng)絡(luò)或磁盤上讀取了字節(jié)流助隧,那么獲得的數(shù)據(jù)就是bytes。要把bytes變?yōu)閟tr,就需要用到decode()方法并村。
decode()函數(shù).png

如果bytes中包含無法解碼的字節(jié)巍实,decode()方法會報錯:

decode()函數(shù)報錯.png

如果bytes中只有一小部分無效的字節(jié),可以傳入errors='ignore'忽略錯誤的字節(jié):

ignore.png
  • len():計算str的字符數(shù)哩牍,如果換成bytes棚潦,len()函數(shù)就計算字節(jié)數(shù)。
len()函數(shù).png

通過len()的計算我們發(fā)現(xiàn):1個中文字符經(jīng)過UTF-8編碼后通常會占用3個字節(jié)膝昆,而1個英文字符只占用1個字節(jié)丸边。
在字符串處理中,我們會經(jīng)常遇到str和bytes的互相轉(zhuǎn)換荚孵。為了避免亂碼問題妹窖,應當堅持使用UTF-8編碼對str和bytes進行轉(zhuǎn)換的好習慣。

由于Python源代碼也是一個文本文件收叶,當我們的源代碼中包含中文的時候骄呼,如果不用指定的編碼保存源代碼,當Python解釋器讀取源代碼時判没,展現(xiàn)在我們眼前的就可能是亂碼蜓萄。所以我們務(wù)必要用UTF-8編碼保存源代碼,當Python解釋器讀取源代碼時讓它按UTF-8編碼讀取澄峰。因此我們通常在文件開頭寫上這兩行:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注釋是為了告訴Linux/OS X系統(tǒng)嫉沽,這是一個Python可執(zhí)行程序,Windows系統(tǒng)會忽略這個注釋俏竞;
第二行注釋是為了告訴Python解釋器绸硕,按照UTF-8編碼讀取源代碼。
申明了UTF-8編碼并不代表我們的.py文件就是UTF-8編碼的魂毁,必須要確保文本編輯器正在使用UTF-8 without BOM編碼:

文本編輯器.png

如果.py文件本身使用UTF-8編碼玻佩,并且也申明了# -- coding: utf-8 --,打開命令提示符測試就可以正常顯示中文:

顯示中文.png

字符串的格式化

最后一個常見的問題是如何輸出格式化的字符串漱牵。我們經(jīng)常會輸出類似'x年x班的xxx夺蛇,今年xx歲疚漆,數(shù)學期末成績是xx'之類的字符串酣胀,而xxx的內(nèi)容都是根據(jù)變量變化的,所以娶聘,需要一種簡便的格式化字符串的方式闻镶。

在Python中,采用的格式化方式和C語言是一致的丸升,用%實現(xiàn)铆农,舉例如下:

格式化.png

%運算符就是用來格式化字符串的。在字符串內(nèi)部,%s表示用字符串替換墩剖,%d表示用整數(shù)替換猴凹,有幾個%?占位符,后面就跟幾個變量或者值岭皂,順序要對應好郊霎。如果只有一個%?,括號可以省略爷绘。

常見的占位符有:

占位符 替換內(nèi)容
%d 整數(shù)
%f 浮點數(shù)
%s 字符串
%x 十六進制整數(shù)

其中书劝,格式化整數(shù)和浮點數(shù)還可以指定是否補0和整數(shù)與小數(shù)的位數(shù):

# -*- coding: utf-8 -*-
print('%2d-%02d' % (3, 1))
print('%.2f' % 3.1415926)

如果你不太確定應該用什么,%s永遠起作用土至,它會把任何數(shù)據(jù)類型轉(zhuǎn)換為字符串:

>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'

有些時候购对,字符串里面的%是一個普通字符怎么辦?這個時候就需要轉(zhuǎn)義陶因,用%%來表示一個%:

>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'
  • format()

另一種格式化字符串的方法是使用字符串的format()方法骡苞,它會用傳入的參數(shù)依次替換字符串內(nèi)的占位符{0}、{1}……坑赡,不過這種方式寫起來比%要麻煩得多:

>>> 'Hello, {0}, 成績提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成績提升了 17.1%'

小結(jié)

Python 3的字符串使用Unicode烙如,直接支持多語言。
當str和bytes互相轉(zhuǎn)換時毅否,需要指定編碼亚铁。最常用的編碼是UTF-8。Python當然也支持其他編碼方式螟加,比如把Unicode編碼成GB2312:

>>> '中文'.encode('gb2312')
b'\xd6\xd0\xce\xc4'

但這種方式純屬自找麻煩徘溢,如果沒有特殊業(yè)務(wù)要求,請牢記僅使用UTF-8編碼捆探。
格式化字符串的時候然爆,可以用Python的交互式環(huán)境測試,方便快捷黍图。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曾雕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子助被,更是在濱河造成了極大的恐慌剖张,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揩环,死亡現(xiàn)場離奇詭異搔弄,居然都是意外死亡,警方通過查閱死者的電腦和手機丰滑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門顾犹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事炫刷∏姹Γ” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵浑玛,是天一觀的道長认臊。 經(jīng)常有香客問我,道長锄奢,這世上最難降的妖魔是什么失晴? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮拘央,結(jié)果婚禮上涂屁,老公的妹妹穿的比我還像新娘。我一直安慰自己灰伟,他們只是感情好拆又,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著栏账,像睡著了一般帖族。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挡爵,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天竖般,我揣著相機與錄音,去河邊找鬼茶鹃。 笑死涣雕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的闭翩。 我是一名探鬼主播挣郭,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疗韵!你這毒婦竟也來了兑障?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蕉汪,失蹤者是張志新(化名)和其女友劉穎流译,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肤无,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡先蒋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年骇钦,在試婚紗的時候發(fā)現(xiàn)自己被綠了宛渐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窥翩,靈堂內(nèi)的尸體忽然破棺而出业岁,到底是詐尸還是另有隱情,我是刑警寧澤寇蚊,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布笔时,位于F島的核電站,受9級特大地震影響仗岸,放射性物質(zhì)發(fā)生泄漏允耿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一扒怖、第九天 我趴在偏房一處隱蔽的房頂上張望较锡。 院中可真熱鬧,春花似錦盗痒、人聲如沸蚂蕴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骡楼。三九已至,卻和暖如春稽鞭,著一層夾襖步出監(jiān)牢的瞬間鸟整,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工朦蕴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吃嘿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓梦重,卻偏偏與公主長得像兑燥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子琴拧,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 總有一些人降瞳,路過你的身邊,波動著你的心弦蚓胸。你不知道挣饥,這個人能在你身邊停留多久。沛膳。扔枫。。锹安。所以短荐,你不敢動心倚舀。 愿你只有...
    口天豐色閱讀 137評論 0 0
  • 第一組最佳文章《下一個決心,讓夢更近》 姓名:章琳題目:下一個決心忍宋,讓夢更近痕貌。點評:陳艷文章讓人能感受到到戰(zhàn)友的熱...
    達芬奇X閱讀 216評論 0 0
  • 寒假里的兩天舵稠,我一頁一頁地看完了這本書,后來入宦,又從頭到尾看了三遍哺徊。 不知道是自己真忙,還是根本就沒興趣了乾闰。大學念了...
    14廣告楊丹年閱讀 611評論 0 3