字串及編碼

      在〈字串及編碼〉中尚無留言

 ASCII編碼

電腦是美國人發明的, 所以當初他們只把英文字母及一些符號數字進行編碼, 產生了127個ASCII的編碼原則. 比如
A : 65
a : 97
0 : 48
空格 : 32

Unicode編碼

到了中文, 日文等複雜的語系時, 127個編碼當然不夠使用, 此時就需使用二個byte以上來表示這些語言.

但各國有各自的編碼原則, 比如中文就有繁体BIG5及簡体的GB2312編碼. 而全世界上百種語言, 這樣在多國語言混合時, 就產生了衝突而顯示出亂碼來.

為了解決多國語言的問題, Unicode因此而生. 通常採用2個byte表示一個字. 當然, 不是固定只有2 byte, 遇到比較偏門的文字, 還是會用到4 byte及6 byte。

比如 “中” 這個字, 在Unicode 的編碼就是 20013

UTF-8編碼

使用Unicode可以解決亂碼問題. 但也衍生了另一個問題. 以A而言, Unicode也是65, 不過確是佔了2個byte, 所以二進位為 00000000 01000001 , 前八碼都為 0, 這樣顯然浪費了一些空間. 而如果文件中大部份都是英文的話, 那浪費的空間就更多了.

為了解決上述問題, 新的utf-8編碼方式得以產生. utf-8採可變動長度的編碼方式. 比如是英文時, 就採用1 byte, 中文就採用3 byte, 偏門字就採4 – 6 byte. 通常用於低速儲存裝置或網路傳輸上. 比如web server就會將動態生存的Unicode, 先轉碼成utf-8, 再傳輸到網路上, 然後在瀏覽器上也是以utf-8顯示出來.

Python支援

Python 3使用Unicode編碼方式. 比如 print(‘這是中文字串’), 印出來的就是中文的字串.

另外Python提供二個函數進行轉換

ord(‘中’) : 將字元轉成Unicode
chr(20013) : 將Unicode轉成字元

print("Unicode : ",ord('中'))
print("字元 : ", chr(20013))

結果如下
Unicode : 20013
字元 : 中

如果知道字元的 16 進位 Unicode, 也可以使用 \uXXXX來表示字元, 如下

a="\u4e2d\u6587"
print(a)

轉碼

字串轉byte–encode

Python處理字串時採用Unicode, 但若要傳輸到網路上, 或儲存在硬碟上, 則要轉成byte.

字串如果只有英文, 比如 a=”ABC”, 則可以使用 “b” 前綴字改成以ascii為編碼的byte資料, 如 a=b”ABC”. 此時把a印出來, 雖然也是印出ABC, 但前面有加上 b, 表示傳輸出去的, 是以 byte為主的。

如果字串有中文的話, 比如a=”中文測試”, 加上前綴字如下 : a=b”中文測試”, 此時因為中文是無法轉成ascii的, 所以會發生錯誤 : SyntaxError: bytes can only contain ASCII literal characters.

那怎麼轉成byte呢?? 當然, 需跟電腦說明要轉成什麼碼. 使用 “ABC”.encode(“utf-8″). encode需指定轉碼格式, 如”utf-8”, “big5”. 從下面的例子可得知, utf-8使用 3byte,  big5使用 2 byte‧

a="中文".encode("big5")
print("big5 : ", a, "每個字使用 2byte")
a="中文".encode("utf-8")
print("utf-8 : ", a, "每個字使用 3byte")

結果如下
big5 : b'\xa4\xa4\xa4\xe5' 每個字使用 2byte
utf-8 : b'\xe4\xb8\xad\xe6\x96\x87' 每個字使用 3byte

btye轉字串 – decode()

相對的, 如果要網路或硬碟讀取進來的, 是byte的資料格式, 此時就需使用decode()解碼成字串

a=b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
print(a)

結果
中文

如果bytes中包含了無法解碼的字元, decode()就會回報錯誤 :  UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte

如果bytes中只有一小部份是無效的字元, 可以使用errors=’ignore’ 參數忽略錯誤的字元.

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

結果 : 
中

len()

len()參數如果為字串, 則計算字串長度. 如果為bytes, 則計算有幾個 byte, 如下

print(len("中文")) <== 結果為 2 
print(len("中文".encode("utf-8"))) <== 結為 6

標示編碼

程式碼中, 為了標示本程式採用utf-8, 通常會於開頭撰寫如下二行

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

第一行只對Linux有效, Windows無效. 第二行則標示為 utf-8. 另如果使用notepad++時, 請記得以而將檔案編碼方式改為 UTF-8 without BOM

格式化

若要印出 — 單價 : 100, 數量 : 10, 總價 : 1000
則可以使用跟C語言一樣的格式化列印
%d: 整數
%f : 小數
%s : 字串
%x : 16進位

上述也可標示列印位數, 如 %.2f, 表示只印二位小數

如下所示

price=10.6
qty=10
print("單價 : %.2f, 數量 : %d, 總價 : %f" % (price, qty, price*qty))

 若要列印 “%”, 則必需寫成如下

print("%.2f%%" % 10.6)

Format

format是另一種格式化的方式, 可以在字串中使用  {0}, {1} 的格式, 然後將要取代的字串, 由 format()的參數取得, 有點像C#的寫法. format為字串的物件方法

a="單價 : {0}, 數量 : {1}, 總價 : {2}".format(price, qty, price*qty)
print(a)

其他編碼

Python除了可以編碼成utf-8之外, 也可編碼成big5, GB2313. 但轉成其他的編碼只是突增困擾而以.

replace

replace可以將某個字元給取代. 請注意, 因為字串是不可變的, 所以如下的寫法, 還是 “abc”.
如果寫成 a=a.replace(‘a’, ‘A’), 印出來才會是Abc

a = 'abc'
a.replace('a', 'A')
print(a)
結果
abc

字串相加

可用 “+” 或 __add__()函數

a="abc"
b="def"
c=a+b
d=a.__add__(b)
print(c)
print(d)

高效字串相加

上述使用 + 相加, 其效能非常的差. 高效方法如下

strlist=[]
strlist.append('first')
strlist.append('second')
strlist.append('third')
strlist.append('forth')
str=''.join(strlist)

請注意, 一定要用 ”.join , 若使用 ‘xxx’.join(strlist), 則會產生 firstxxxsecond……, xxx會插入到第二個位置

split

將定串依指定字串拆開, 並傳回List

如果字串有二個 ‘,’ 所以如果依 ‘,’ 拆開, 就會產生三個元素的List, 第二個字串為空字串

print('Thomas,,彰化市中山路一段1號'.split(','))
結果:
['Thomas', '', '彰化市中山路一段1號']

index

a='Thomas 彰化市中山路一段1號'
print(a.index('一段'))
結果 :
13

子字串

‘ABCDEFGHIJKLM'[啟始位置:結束位置],
啟始位置的字串索引編號由 0 開始(‘A’ 的編號為0)
結束位置由字串索引編號由 1 開始(‘A’ 的編號為1)

a='ABCDEFGHIJKLM'
print(a[1:3])
結果 : 
BC

字串自動補0

t='123'
t=t.zfill(5)
print(t)

結果為 : 00123

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *