2.5. 字串方法與格式化

字串內建了一整套用於檢視與重塑的方法工具箱。由於字串是不可變的,每個方法都會回傳一個字串 -- 原始字串不會被改動。

2.5.1. 檢視字串

>>> name = "OpenMV Cam"
>>> name.startswith("Open")
True
>>> name.find("MV")
4
>>> name.count("m")
1
>>> "Cam" in name
True

2.5.2. 清理與大小寫

>>> "  hello  ".strip()
'hello'
>>> "abc-123".replace("-", "_")
'abc_123'
>>> "OpenMV".lower()
'openmv'

2.5.3. 分割與接合

  • str.split() -- 在分隔符每次出現之處將字串拆成一個串列(預設:任何連續空白)。

  • str.join() -- 反向操作:以接收者作為分隔符,將一序列字串黏接在一起。這是由片段建構長字串的高效率方式。

>>> "1,2,3".split(",")
['1', '2', '3']
>>> "hello world".split()
['hello', 'world']
>>> ", ".join(["a", "b", "c"])
'a, b, c'

2.5.4. f-字串

將值內插到字串中最簡單的方式是 f-字串 -- 一個以 f 為前綴的字串字面值。{} 內的任何運算式都會被求值並插入:

>>> name = "OpenMV"
>>> count = 42
>>> f"{name} saw {count} blobs"
'OpenMV saw 42 blobs'

大括號內的冒號會引入一個格式規格,用以控制值如何呈現:

  • {x:.2f} -- 小數點後保留 2 位數的浮點數。

  • {x:>10} -- 在 10 個字元寬的欄位內靠右對齊。

  • {x:<10} -- 靠左對齊。

  • {x:0>4} -- 以前導零填補至寬度 4。

  • {x:#x} -- 帶有 0x 前綴的十六進位。

  • {x:b} -- 二進位表示法。

>>> f"pi is roughly {3.14159:.3f}"
'pi is roughly 3.142'
>>> f"reg = {0xAB:#x}"
'reg = 0xab'
>>> for i in range(3):
...     print(f"line {i:0>3}")
line 000
line 001
line 002

在運算式名稱後加上單一的 = 會同時印出名稱與值 -- 對快速除錯列印很方便:

>>> v = 3.14
>>> print(f"{v=}")
v=3.14

2.5.4.1. 整數進位轉換

有三個內建函式做的工作與 :b / :o / :x 格式規格相同,但會直接回傳轉換後的字串:

  • bin() -- 二進位,帶有 "0b" 前綴。

  • oct() -- 八進位,帶有 "0o" 前綴。

  • hex() -- 十六進位,帶有 "0x" 前綴。

>>> hex(255)
'0xff'
>>> bin(10)
'0b1010'
>>> oct(8)
'0o10'

反向操作 -- 將一個 N 進位字串轉回整數 -- 則使用 int 建構函式並明確指定進位:

>>> int("ff", 16)
255
>>> int("0b1010", 2)         # the "0b" prefix is allowed
10

當你想取得整數的原始字串時(用於記錄行、設定檔、暫存器傾印)就用這些函式。當你想要填補、寬度,或想在同一個 f-字串中把值與其他文字混合時,則使用格式規格。

2.5.5. 較舊的格式化風格

f-字串是建議的風格,但仍有兩種較舊的作法可用,並會出現在既有程式碼中:

str.format() -- 大括號搭配傳給模板字串上 .format() 方法的位置或關鍵字引數:

>>> "Hello, {}".format(name)
'Hello, OpenMV'
>>> "{0} + {0} = {1}".format(2, 4)
'2 + 2 = 4'
>>> "{name}: {value}".format(name="frames", value=42)
'frames: 42'

格式規格({:.2f}{:>10}、...)的運作方式與 f-字串相同;唯一的差別在於值是在何處提供的。

% 格式化(printf 風格)-- 單一的 % 運算子會把值代入格式碼中,一個值對應一個格式碼。多個值請以元組傳入:

>>> "Hello, %s" % name
'Hello, OpenMV'
>>> "%d + %d = %d" % (2, 2, 4)
'2 + 2 = 4'
>>> "%.2f" % 3.14159
'3.14'

最常見的型別碼是 %s(字串)、%d(整數)、%f(浮點數)與 %x(十六進位)。

每個 % 格式碼都可在 % 與型別字母之間帶有修飾符。完整形式為 %[flags][width][.precision]type

  • width -- 欄位必須佔用的最小字元數。較短的值會以空格填補;較長的值則溢出。%10d 保留 10 個字元並將數字靠右對齊。

  • precision -- 意義取決於型別。對浮點數而言是小數點後的位數。%.2f 給出兩位小數。對字串而言是要取用的最大字元數(%.5s 截斷成五個字元)。

  • 靠左對齊 -- - 旗標將欄位置於左側。%-10d 將數字置於左側並補上尾隨空格。

  • 補零 -- 0 旗標以前導零(而非空格)填補(用於數值型別)。%05d 以零補滿至五位數。

  • 正負號 -- + 旗標永遠在數字上顯示正負號,包括為正數加上 +

  • 替代形式 -- # 旗標。對 %x 而言會在輸出前加上 0x;對 %o 而言則加上 0o

旗標、寬度與精確度可以組合使用:

>>> "%10d" % 42
'        42'                 # width 10, space-padded, right-aligned
>>> "%-10d|" % 42
'42        |'                # width 10, left-aligned
>>> "%05d" % 42
'00042'                      # width 5, zero-padded
>>> "%8.2f" % 3.14159
'    3.14'                   # width 8, 2 decimal places
>>> "%08.2f" % 3.14159
'00003.14'                   # width 8, zero-padded
>>> "%+d" % 42
'+42'                        # explicit sign
>>> "%#06x" % 0xAB
'0x00ab'                     # 0x prefix, zero-pad to 6 chars total

兩種較舊的風格都比 f-字串更難閱讀、也更容易出錯 -- 撰寫新程式碼時請採用 f-字串,並在閱讀既有程式碼時能辨認出這些較舊的形式。