Python基礎(二)字符串和編碼

注:本文的Python學習系列是筆者在學習廖雪峯老師的Python教程所記錄下的學習筆記,如果想了解更多Python系列的學習資料可以看看 廖雪峯 Python教程

知識回顧:
在上一章的 Python基礎(一)數據類型與變量學習了Python 的基本數據類型與邏輯運算符號,比較簡單。這一章就一起來複習一下計算機的基礎編碼格式把…

一,字符編碼

背景:

計算機只能處理數字,如果要處理文本,就必須要先把文本轉換爲數字才能處理。在最早的計算機設計時採用8個比特(bit)作爲一個字節,所以一個字節能表示的最大整數就是 255(二進制 11111111 = 十進制 255),如果要表示更大的整數,就必須用更多的字節比如,2個字節能表示的最大整數是65535,4個字節能表示的最大整數是 4294967295

種類與區別:

1,由於計算機是美國人發明的,因此最早只有127個字符被編碼到計算機裏面去,也就是 ASCII 碼。比如大寫字母A 是65 ,小寫字母z 是122。
在這裏插入圖片描述
(貼出來看看,看不懂也沒關係…)

2,但是要處理中文顯然一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII碼衝突,所以中國定製了 GB2312編碼,用來把中文編進去。

3,你可以想到全世界有上百種語言,日本把日文編到 shift_JIS 裏,韓國把韓文編到 Euc-kr 裏。
各國都有自己的標準,就會不可避免的出現衝突。結果就是在多語言的混合文本里面,顯示出來會有亂碼。
因此,Unicode 因運而生!Unicode把所有語言都統一到一套編碼裏面,這樣就不會出現亂碼的問題了。

4,捋一捋ASCII碼與Unicode碼的區別。
Unicode最常用的是用兩個字節表示一個字符,特殊情況下特別偏僻的字符,需要4個字節。現在大多數操作系統與編程語言都支持Unicode碼。
ASCII碼編碼是1個字節,而Unicode碼編碼通常是2個字節。

列如:
字符A 用ASCII編碼是十進制的65,二進制的 01000001
字符0 用ASCII編碼是十進制的48,二進制的 00110000,注意字符’0’ 跟整數 0 是不一樣的。
漢子’中’ 已經超出了ASCII碼的範圍,用Unicode編碼 是十進制的 20013,二進制的 01001110 00101101

你可以猜測,如果把ASCII碼的A用Unicode編碼,只需要在前面補0就可以了,因此 A的Unicode碼 是00000000 01000001
這樣新的問題又來了,如果統一成Unicode碼,那麼從此亂碼問題消失了。但是如果你寫的文本基本上都是英文的話,用Unicode編碼比ASCII碼會多出一倍
的儲存空間,那麼在儲存跟文件傳輸的過程中就變得十分不划算了。
所以,本着節約資源的精神,又出現把Unicode碼轉換成“可變長編碼”的 UTF-8 編碼。UTF-8編碼把一個Unicode字符根據不同大小編碼成1-6個字節 ,常用的英文字母被編碼成1個字節,漢字通常是3個字節,只有很生僻的字符纔會用 4-6個字節。如果你要傳輸的文本包含大量的英文字符,用UIF-8 就能節省出很多空間。

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
x 01001110 00101101 11100100 10111000 10101101

從上面的表格還可以發現,UTF-8編碼有一個額外的好處,就是ASCII編碼實際上可以被看成是UTF-8編碼的一部分,所以,大量只支持ASCII編碼的歷史遺留軟件可以在UTF-8編碼下繼續工作。
搞清楚了ASCII碼,Unicode碼,和UTF-8的關係,我們就可以總結一下現在計算機系統通用編碼的工作方式:
1,在計算機內存中,統一使用了Unicode編碼,當需要保存硬盤或者需要傳輸數據的時候,就轉換成 UTF-8編碼。
2,用記事本編輯的時候,從文件裏面被讀取的UTF-8字符,被轉換成Unicode字符到內存裏,編輯完成後,保存的時候在把Unicode轉換成UTF-8保存文件。
在這裏插入圖片描述

二,Python字符串

搞清楚了讓人頭痛的字符編碼問題後,一起來研究Python的字符串。
在最新的Python 3版本中,字符是以Unicode編碼的,也就是說Python字符串支持多語言。

對於單個字符的編碼,Python提供了 ord() 函數獲取字符的整數表示, chr() 函數把編碼轉換成對應的字符

>>>ord('A')
65
>>>ord('中')
20013
>>>chr(66)
'B'
>>>chr(25991)
'文'

由於Python中的字符是 str ,在內存中用Unicode表示,一個字符對應若干字節。如果要在網絡上傳輸,或者保存到磁盤上,就需要把str 變成以字節爲單位的 bytes。
Python對 bytes類型的數據用 帶b 前綴的單引號或者雙引號表示:

x = b'ABC'

要注意區分’ABC’ 跟 b’abc’ ,後者雖然內容顯示的跟前者一樣,但bytes的每個字符都佔用一個字節。

一,以Unicode表示的str 通過 encode() 方法可以編碼爲指定的bytes :

>>> 'ABC'.encode('ascii')
b'ABC'
>>>'中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'

二,反過來,從網絡上或者磁盤上讀取了字節流,那麼讀到的數據就是 bytes,要把bytes轉換成 str ,就需要用到decode() 方法:

>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'

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

>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'

四,要計算str 包含多少個字節時 可以用 len() 函數

>>> len('ABC')
3
>>> len('中文')
2

五,len() 函數在計算str 時 表示字符長度,如果是計算bytes 時就計算的字節數.

>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6

可見,1箇中文字符經過UTF-8編碼後通常會佔用3個字節,而1個英文字符只佔用1個字節。
在操作字符串時,我們經常遇到str和bytes的互相轉換。爲了避免亂碼問題,應當始終堅持使用UTF-8編碼對str和bytes進行轉換。
由於Python源代碼也是一個文本文件,所以,當你的源代碼中包含中文的時候,在保存源代碼時,就需要務必指定保存爲UTF-8編碼。 當Python解釋器讀取源代碼時,爲了讓它按UTF-8編碼讀取,我們通常在文件開頭寫上這兩行:

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

第一行註釋是爲了告訴Linux/OS X系統,這是一個Python可執行程序,Windows系統會忽略這個註釋;
第二行註釋是爲了告訴Python解釋器,按照UTF-8編碼讀取源代碼,否則,你在源代碼中寫的中文輸出可能會有亂碼。
申明瞭UTF-8編碼並不意味着你的.py文件就是UTF-8編碼的,必須並且要確保文本編輯器正在使用UTF-8 without BOM編碼:

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

三,Python 字符串格式化
最後一個常見的問題是 如何輸出格式化的字符串,我們經常會在log裏面輸出類似 ‘親愛的xxx你好!你xx月的話費是xx,餘額是xx’ 之類的字符串

在Python中,採用的格式化方式和C語言是一致的,用%實現,舉例如下:

>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'

常見的佔位符有:

佔位符 替換內容
%d 整數
%f 浮點數
%s 字符串
%x 十六進制整數

如果你不太確定應該用什麼,%s永遠起作用,它會把任何數據類型轉換爲字符串:

>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'
有些時候,字符串裏面的%是一個普通字符怎麼辦?這個時候就需要轉義,用%%來表示一個%:
>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'

format()
另一種格式化字符串的方法是使用字符串的format()方法,它會用傳入的參數依次替換字符串內的佔位符{0}、{1}……,不過這種方式寫起來比%要麻煩得多:
>>> 'Hello, {0}, 成績提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成績提升了 17.1%'
ok~ 到此Python基礎(二)編碼和字符串就結束了… ,經驗+50 火罐哥布林升級爲 3級極冰哥布林 QWER~~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章