字串
April 9, 2022Python 的字串有多種的表示方式。最基本的是實字表示方式,使用雙引號或單引號來包括字元序列:
>>> "Justin"
'Justin'
>>> 'Justin'
'Justin'
>>> "Just'in"
"Just'in"
>>> 'Just"in'
'Just"in'
>>> 'Just' 'in'
'Justin'
字串表示
單引號或雙引號的字串表示,可以交替使用,就像上例中,若要在字串中包括單引號,則使用雙引號包括字元序列,反之亦然。如果有兩個連續的字串實字,會自動將之結合為一個字串。
撰寫字串致力於簡潔易讀,字串中若包括 \
,某些情況下不用特別處理,會自動轉換為 \\
,因此可以直接如下撰寫字串:
>>> 'c:\workspace'
'c:\\workspace'
>>> 'c:\\workspace'
'c:\\workspace'
>>>
直接撰寫 'c:\workspace'
就如同自行撰寫 'c:\\workspace'
,前者在撰寫與可讀性上都比較方便。\\
是轉義(Escape)字串表示,來看一些常用的轉義(Escape)字串表示:
\\
:反斜線。\'
:單引號 ‘。\"
:雙引號 “。\ooo
:以 8 進位數字 ooo 表示字元碼點(Code point),最多三位數,例如'\101'
表示字串'A'
。\xhh
:以 16 進位數字 hh 表示字元碼點,例如'\x41'
表示字串'A'
。\uhhhh
:以 16 進位數字 hhhh 表示字元碼點,例如'\u54C8\u56C9'
表示'哈囉'
。\Uhhhhhhhh
:以 16 進位數字 hhhhhhhh 表示字元碼點,例如'\U000054C8\U000056C9'
表示'哈囉'
,'\U0001D11E'
表示高音譜記號。\0
:空字元。\n
:換行。\r
:歸位。\t
:Tab。
在一些程式語言中(例如 Java、JavaScript),字串轉義表示會有碼元(Code unit)、代理對(Surrogate pair)之類的問題,Python 3.x 完全支援 Unicode,只需選擇適當的格式來表示碼點。
因此,想要以字串表示 \t
這類文字,必須撰寫 '\\t'
來表示,這有些不方便,這時你可以使用原始字串(Raw String)表示,只要在字串前加上 r
即可。例如:
>>> print('\t')
>>> print('\\t')
\t
>>> print(r'\t')
\t
>>> print('c:\\workspace')
c:\workspace
>>> print(r'c:\\workspace')
c:\\workspace
>>> '\t'
'\t'
>>> r'\t'
'\\t'
>>> 'c:\\workspace'
'c:\\workspace'
>>> r'c:\\workspace'
'c:\\\\workspace'
>>>
如果你的字串內容必須跨越數行,可以使用三重引號。例如:
>>> '''Justin is caterpillar!
... caterpillar is Justin!'''
'Justin is caterpillar!\n caterpillar is Justin!'
>>> text = '''Justin is caterpillar!
... caterpillar is Justin!'''
>>> print(text)
Justin is caterpillar!
caterpillar is Justin!
>>>
在三重引號之間輸入任何內容,則最後的字串就照單全收,包括換行、縮排等。
字串操作
如果想知道字串的長度,則可以使用 len
函式。例如:
>>> text = 'Justin'
>>> len(text)
6
>>>
可以使用 for
迴圈逐一取出字串中的字元:
>>> for c in 'Justin':
... print(c, end='-')
...
J-u-s-t-i-n->>>
或者是使用 in
運算子測試某個字串是否在原字串中:
>>> 'Just' in 'Justin'
True
>>>
可以使用 +
運算子來串接字串,使用 *
可以重複字串:
>>> text1 = 'Just'
>>> text2 = 'in'
>>> text1 + text2
'Justin'
>>> text1 * 10
'JustJustJustJustJustJustJustJustJustJust'
>>>
字串是不可變動的(Immutable),+
實際會產生新字串。
在強弱型別的光譜中,Python 比較偏強型別,型態較不能自行轉換,例如 Python,不能混合字串與數字進行 +
運算,你得自己將數字轉為字串,才可以進行字串串接:
>>> 'score: ' + 90
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> 'score: ' + str(90)
'score: 90'
>>>
如上例所示,可以使用 str
將數值轉換為字串。
字串是由字元序列所組成,如果想取得字串中某個字元,可以使用 []
指定索引,索引從 0 開始。例如:
>>> name = 'Justin'
>>> name[0]
'J'
>>> name[1]
'u'
>>> name[-1]
'n'
>>>
索引可指定正值,還可以指定負值,實際上了解索引意義的開發人員,都知道索引其實就是相對第一個元素的偏移值,在 Python 中,正值索引就是指正偏移值,負值索引就是負偏移值,也就是 -1 索引就是倒數第一個元素,-2 索引就是倒數第二個元素。
[]
運算子還可以進行切片(Slice)運算。例如:
>>> name[0:3]
'Jus'
>>> name[3:]
'tin'
>>> name[:4]
'Just'
>>> name[:-1]
'Justi'
>>> name[-5:-1]
'usti'
>>>
上例中指出了切片運算,可以指定起始索引(包括)與結尾索引(不包括)來切出子字串。如果只指定起始索引,不指定結尾索引,則表示切出從起始索引至字串結束間的子字串。如果只指定結尾索引,不指定起始索引,則表示切出從 0 索引至(不包括)結尾索引間的子字串。起始索引與結尾索引都可以指定負值。([:]
則是作淺層複製,只不過對字串這種不可變動的物件沒有實質意義)
切片運算的另一個形式是 [i:j:k]
,意思是切出起始索引 i
與結尾索引 j
(不包括)之間,每隔 k
元素的內容。例如:
>>> name[0:4:2]
'Js'
>>> name[2::2]
'si'
>>> name[:5:2]
'Jsi'
>>> name[::2]
'Jsi'
>>> name[::-1]
'nitsuJ'
>>>
當間隔指定為正時,表示正偏移每 k
個取出元素,間隔指定為負時,表示負偏移每 k
個取出元素。[::-1]
表示從索引 0 至結尾,以負偏移 1 方式取得字串,結果就是反轉字串。
字串碼點/編碼
如果想知道某個字元的碼點並以整數表示,可以使用 ord
函式,使用 chr
可以將指定的碼點整數表示轉換為字元:
>>> ord('元')
20803
>>> chr(20803)
'元'
>>>
從Python 3以後,每個字串都包含了 Unicode 字元,字串都是 str
實例,如果想將字串轉為指定的位元組編碼,可以使用 encode
方法,這會取得 bytes
實例,如果有個 bytes
實例,也可以使用 decode
方法指定編碼取得 str
實例:
>>> '元'.encode('big5')
b'\xa4\xb8'
>>> '元'.encode('utf-8')
b'\xe5\x85\x83'
>>> '元'.encode('big5').decode('big5')
'元'
>>>
搞不清楚誰可以用 encode
而誰可以用 decode
嗎?'\xe5\x85\x83'
這樣的資訊,人類不容易理解,編碼就是將可理解的東西,變為不容易理解的資訊(encode
),反之將不易理解的資訊,變為可理解的東西就是解碼(decode
)。
在 REPL 顯示結果可以看到,可以在字串前加上 b
來建立 bytes
,這是從 Python 3.3 以後開始支援的語法,也可以在字串前加上 u
,結果會是個 str
,u
只是當初要推廣 Python 3.x,為了多一點與 Python 2 的相容性而加入;然而就現今 Python 3 的採用率來說,不用特別加上 u
了。