Python 的內建函式 print() 是最常用來輸出變數值的工具, 除了在開發過程中 debug 時用來檢視變數之值外, 也可以用在輸出報表時控制文字的輸出格式, 本篇對 Python 演化的過程中陸續發展出 % 運算子, format() 方法, 以及 f 字串這三種格式化字串輸出方式做了摘要整理與測試.
參考文章 :
參考書籍 :
# 增壓的 Python (碁峰, 2020)
# Python 神乎其技 (全新超譯版, 旗標, 2020)
# Python 也可以這樣學 (博碩, 董付國, 2018)
Python 內建函式 print() 的語法如下 :
print(value1, value2, .... [, sep=' ', end='\n'])
其中 value1, value2, ... 等參數為要輸出的變數或字面值 (literal), 亦即 print() 可以一次輸出多個值, 各個值以逗號隔開. 備選的關鍵字參數 sep 是用來隔開這些輸出資料的字串, 預設是一個空白字元; 而參數 end 是全部輸出結束時放在結尾的字串, 預設是換行字元 '\n', 故每次呼叫 print() 預設都會換行輸出, 若不要換行則需用 end 設定為其它字串, 例如 end 設為空字元會讓下一次 print() 的輸出緊接在此次 print() 輸出的後面.
除了單純輸出資料外, print() 還可以控制輸出的格式, 在 Python 的發展過程中產生了三種格式化輸出方式, Python 2.x 使用 % 字元做為控制格式的運算子, Python 3 之後則在字串物件上新增了 format() 方法 (此方法後來也反向移植到 Python 2.7 裡), 而 Python 3.6 以後則新增了效率更好的 f 字串用法, 可以在字串中直接嵌入變數.
1. 使用 % 運算子 :
這是 Python 最早的字串格式化做法, 它是在字串中使用 % 運算子控制對應的變數在字串中的輸出格式, 其語法如下 :
print("...%? .... %?" % (var1, var2, ...)) # 其中 %? 為格式化字串
print() 傳入參數分成三部分 :
前面部分是內嵌格式化字串 %? 的輸出字串, 中間是 % 字元, 後面部分是要嵌入的變數序列元組 (對應前面的格式化字串), 變數數目需與前面輸出字串內的格式化字串 %? 數目一致, 輸出時將以對應之格式逐一插入字串中. 這三個部分可以連寫, 不需要用空格隔開, 但為了提高可讀性, 通常會用空格隔開. 如果只有一個變數要輸出, 則 tuple 的小括弧可以省略.
% 格式化字元可控制變數輸出時的對齊方式, 正數是否冠 + 號, 空位是否補 0, 最小輸出長度, 以及精確度等, 語法如下 :
%[-][+][0][寬度][.精確度]型態
中括號表示可有可無, 說明如下 :
- - : 指定靠左對齊 (即寬度過多時預設為靠右對齊)
- + : 正數前面加上 + 號
- 0 : 寬度過多時空位補 0 (僅用於數值), 預設補空格
- 寬度 : 指定最小輸出寬度 (超出時不受此限制)
- 精確度 : 指定浮點數精確度到小數點後幾位或輸出字串中的前幾個字元
- 型態 : 如 s (字串), d (整數), f (浮點數), e (科學表示法) 等
注意, 浮點數的寬度包含小數點, 資料寬度超過此指定寬度時不會被截斷 (因為這是最小寬度), 而是顯示完整的資料, 但變數值實際寬度小於此最小寬度設定時則會預設補空格 (數值可用 0 格式設為補 0). 資料寬度小於設定時也有對齊問題, 不論字串或數值在 % 格式化裡預設都是靠右對齊. 精確度雖然大部分用在浮點數或其科學表示法, 但也可用在字串, 表示輸出前幾個字元.
另外, 寬度與精確度都可以用變數控制, 這時格式字元要用 * 字元代替明確之整數, 在 % 後面的 tuple 中, 必須在輸出資料的前面依序增加寬度與精確度之設定值 (可用變數), 如下圖所示 :
控制資料型態的格式化字元如下表 :
格式化字元 | 說明 |
d 或 i | 以整數格式輸出 (預設) |
f 或 F | 以浮點數格式輸出數值 |
s | 以字串格式輸出任何資料型態之字串 (無引號) |
r | 以字串格式輸出任何資料型態之字串 (有引號) |
c | 輸出 0~127 整數所代表之 ASCII 字元 |
x | 以小寫之 16 進制格式 (0~9, a~f) 輸出整數 |
X | 以大寫之 16 進制格式 (0~9, A~F) 輸出整數 |
o | 以 8 進制整數格式 (0~7) 輸出整數 |
e | 以小寫 e 科學記號式輸出數值 |
E | 以大寫 E 科學記號式輸出數值 |
g | 以小寫 e 科學記號式輸出數值 (短格式) |
G | 以大寫 E 科學記號式輸出數值 (短格式) |
% | 輸出 % 字元 |
格式化輸出主要分為字串/字元與數值兩類, 其中最常用的是 %d (整數), %f (浮點數), 以及 %s (字串) 這三個, 例如 :
>>> d=123 # 整數
>>> f=3.14159 # 浮點數
>>> s='Hello World' # 字串
>>> print('d=%d f=%f s=%s' % (d, f, s)) # 用適當的格式輸出
d=123 f=3.141590 s=Hello World
如果只有一個資料要輸出, 變數可加或不加小括弧; 但兩個以上則必須加小括弧成為 tuple :
>>> print('d=%d' % d) # 只輸出一個變數時可加或不加小括弧
d=123
>>> print('d=%d' % (d))
d=123
>>> print('d=%d f=%f s=%s' % d, f, s) # 輸出兩個以上變數時必須用 tuple 形式
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: not enough arguments for format string
變數通常應該使用適當的格式輸出 (數值用 %d, %f , %x 等, 字串用 %s), 但所有資料型態都可用 %s 字串格式輸出, 反之則不成立, 字串不可以用數值格式輸出, 例如 :
>>> print('%s' % 123) # 整數可用 %s 格式輸出
123
>>> print('%s' % 3.14159) # 浮點數可用 %s 格式輸出
3.14159
>>> print('%s' % 3e-10) # 浮點數可用 %s 格式輸出
3e-10
>>> print('%d' % '123') # 字串不可用 %d 格式輸出
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: %d format: a number is required, not str
>>> print('%f' % '3.14159') # 字串不可用 %f 格式輸出
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: must be real number, not str
(1). 輸出字串 :
格式字元 s 或 r 可用來輸出字串, 兩者的差別是 %r 輸出的字串有引號, 而 %s 則沒有, 例如 :
>>> print('%s' % 'Hello World')
Hello World
>>> print('%r' % 'Hello World')
'Hello World'
這跟呼叫內建函式 str() 與 repr() 的效果類似, 呼叫後者會在傳入字串外再包一個雙引號 :
>>> str('Hello')
'Hello'
>>> repr('Hello')
"'Hello'"
關於 repr() 與 str() 參考 :
如果有指定寬度, 多出來的空位會補空格且預設向右對齊; 若要向左對齊可用 - 格式. 但實際字串大於指定寬度時會輸出完整字串, 而非截掉字串, 例如 :
>>> print('|%10s' % 'Hello') # 指定寬度 10, 預設向右對齊補空格
| Hello
>>> print('%-10s|' % 'Hello') # 指定寬度 10, 指定向左對齊預設補空格
Hello |
>>> print('%5s' % 'Hello World') # 字串長度超過指定時輸出完整字串
Hello World
字串也可以指定精確度, 它會控制要輸出字串中的前幾個字元, 例如 :
>>> print('%.1s' % 'Hello') # 輸出字串的前 1 個字元
H
>>> print('%.2s' % 'Hello') # 輸出字串的前 2 個字元
He
>>> print('%.3s' % 'Hello') # 輸出字串的前 3 個字元
Hel
>>> print('%.4s' % 'Hello') # 輸出字串的前 4 個字元
Hell
>>> print('%.5s' % 'Hello') # 輸出字串的前 5 個字元
Hello
>>> print('%.6s' % 'Hello') # 輸出字串的前 6 個字元
Hello
+ 格式只用在數值, 對字串無作用, 例如 :
>>> print('%+s' % 'Hello')
Hello
由於 % 被用來識別格式化字串的起點, 如果要輸出 % 本身必須用 %%, 例如 :
>>> print('%d%%' % (42)) # 輸出 % 字元本身
42%
(2). 輸出 ASCII 字元 :
格式字元 c 可用來將 ASCII 碼 (0~127) 輸出為 ASCII 字元, 例如 :
>>> print('%c' % 48) # 輸出 ASCII 碼 48 的字元
0
>>> print('%c' % 57) # 輸出 ASCII 碼 57 的字元
9
>>> print('%c' % 65) # 輸出 ASCII 碼 65 的字元
A
>>> print('%c' % 90) # 輸出 ASCII 碼 90 的字元
Z
這與內建函式 chr() 效果相同, 例如 :
>>> chr(48) # 傳回 ASCII 碼 48 的字元
'0'
>>> chr(57) # 傳回 ASCII 碼 57 的字元
'9'
>>> chr(65) # 傳回 ASCII 碼 65 的字元
'A'
>>> chr(90) # 傳回 ASCII 碼 90 的字元
'Z'
順帶一提, chr() 的反函數是 ord(), 它會傳回傳入字元之 ASCII 碼, 例如 :
>>> ord('0') # 傳回字元 0 的 ASCII 碼
48
>>> ord('9') # 傳回字元 9 的 ASCII 碼
57
>>> ord('A') # 傳回字元 A 的 ASCII 碼
65
>>> ord('Z') # 傳回字元 Z 的 ASCII 碼
90
(3). 輸出整數 :
輸出 10 進制整數可用 %d 格式, 輸出 8 進制整數使用 %o 格式, 輸出 16 進制整數則用 %x 格式 (小寫) 或 %X 格式 (大寫), 但就是缺了輸出二進制整數的格式 (沒有 %b 格式), 例如 :
>>> print('%d' % 123) # 10 進制
123
>>> print('%o' % 123) # 8 進制
173
>>> print('%x' % 123) # 16 進制 (小寫)
7b
>>> print('%X' % 123) # 16 進制 (小寫)
7B
不論哪個進制都可以配合使用 -, +, 0 等格式字元. 指定寬度格式時若整數小於此寬度時預設會向右靠齊, 並在前面空位補空格, 例如 :
>>> print('|%10d' % 12345) # 最小寬度 10, 預設靠右對齊補空格
| 12345
>>> print('|%010d' % 12345) # 最小寬度 10, 預設靠右對齊補 0
|0000012345
>>> print('%-10d|' % 12345) # 最小寬度 10, 指定靠左預設補空格
12345 |
>>> print('%-010d|' % 12345) # 最小寬度 10, 指定靠左補 0 (無作用)
12345 |
>>> print('%3d' % 12345) # 數值長度超過指定時輸出完整數值
12345
可見對整數而言, 指定靠左對齊時右方補 0 是沒作用的. 其它進制也是如此, 例如 16 進制 :
>>> print('|%10x' % 56789) # 16 進制預設靠右補空格
| ddd5
>>> print('%010x|' % 56789) # 16 進制預設靠右補 0
000000ddd5|
>>> print('%-10x|' % 56789) # 16 進制指定靠左補空格
ddd5 |
>>> print('%3x' % 56789) # 數值長度超過指定時輸出完整數值
ddd5
>>> print('%-010x|' % 56789) # 最小寬度 10, 指定靠左補 0 (無作用)
ddd5 |
格式 + 會在正數前面添加 + 號 (0 算正數), 例如 :
>>> print('%+d' % 12345) # 正數會冠 +
+12345
>>> print('%+d' % 0) # 0 被視為正數
+0
>>> print('%+d' % -12345) # 負數不冠 +
-12345
指定精確度對整數沒甚麼意義, 但也不會報錯, 而是輸出完整的數字, 例如 :
>>> print('%.3d' % 12345)
12345
>>> print('%.1d' % 12345)
12345
>>> print('%2.1d' % 12345)
12345
整數可以用 %e 或 %E 格式以科學表示法輸出, 也可以指定精確度, 例如 :
>>> print('%e' % 12345) # 預設顯示到小數第 6 位 (空位補 0)
1.234500e+04
>>> print('%E' % 12345) # 預設顯示到小數第 6 位 (空位補 0)
1.234500E+04
>>> print('%.2e' % 12345) # 顯示到小數 2 位 (四捨五入)
1.23e+04
>>> print('%.2E' % 12345) # 顯示到小數 2 位 (四捨五入)
1.23E+04
>>> print('%e' % 1456789) # 超出小數 6 位則完整輸出
1.456789e+06
>>> print('%.1e' % 1456789) # 顯示到小數 1 位 (四捨五入)
1.5e+06
>>> print('%.1e' % 1446789) # 顯示到小數 1 位 (四捨五入)
1.4e+06
可見 e 或 E 格式預設會顯示到小數點後 6 位, 不足 6 位時空位補 0, 若指定精確度則四捨五入到指定之位數.
(4). 輸出浮點數 :
輸出浮點數使用 %f 格式, 數值預設靠左顯示, 預設顯示到小數 6 位, 若小數部分有空位補 0 到 6 位, 超過則四捨五入到小數 6 位, 例如 :
>>> print('圓周率=%f' % 3.14) # 小數點後不足 6 位補 0
圓周率=3.140000
>>> print('圓周率=%f' % 3.14159) # 小數點後不足 6 位補 0
圓周率=3.141590
>>> print('圓周率=%f' % 3.1415926) # 超過舊四捨五入到小數 6 位
圓周率=3.141593
注意, 對浮點數指定寬度時是包含小數的. 指定精確度時會四捨五入到指定之小數位數; 指定 0 格式時空位會補 0 (預設補空格); 指定 + 格式時正數會顯示 + 號; 指定 - 格式會讓數值靠左對齊 (數值預設靠右對齊), 例如 :
>>> print('圓周率=%12f' % 3.14159) # 預設左方空位補空格
圓周率= 3.141590
>>> print('圓周率=%12.1f' % 3.14159) # 指定顯示小數 1 位 (四捨五入)
圓周率= 3.1
>>> print('圓周率=%12.2f' % 3.14159) # 指定顯示小數 2 位 (四捨五入)
圓周率= 3.14
>>> print('圓周率=%12.3f' % 3.14159) # 指定顯示小數 3 位 (四捨五入)
圓周率= 3.142
>>> print('圓周率=%012.2f' % 3.14159) # 指定左方空位補 0
圓周率=000000003.14
>>> print('圓周率=%+12f' % 3.14159) # 正數顯示 +
圓周率= +3.141590
>>> print('圓周率=%-12f' % 3.14159) # 靠左對齊
圓周率=3.141590
數值也可用 e 與 E 格式固定用科學表示法輸出, 預設顯示到小數點後 6 位, 過長截斷 (不是四捨五入), 空位則補 0. 指定精確度時會四捨五入到指定之小數位數, 指定寬度時寬度指的是從小數點後面起算的位數 (包含指數部分), 例如 :
>>> print('%e' % 1.23456789) # 預設顯示到小數點後 6 位 (截斷)
1.234568e+00
>>> print('%e' % 0.123456789)
1.234568e-01
>>> print('%e' % 0.0123456789)
1.234568e-02
>>> print('%+e' % 0.0123456789) # 正數顯示 + 號
+1.234568e-02
>>> print('%.2e' % 0.0123456789) # 指定精確度到小數後 2 位 (四捨五入)
1.23e-02
>>> print('%.3e' % 0.0123456789) # 指定精確度到小數後 3 位 (四捨五入)
1.235e-02
>>> print('%10e' % 0.0123) # 指定小數點後 6 位
1.230000e-02
格式 g 與 G 會根據值的大小自動選擇用整數, 浮點數, 或科學表示法來輸出數值, 小數部分若與整數部分比起來小很多, 則小數部分會被捨棄. 指數超過 6 次方或小於 -5 次方時時會以科學表示法輸出 (相當於使用 e 或 E 格式), 在這範圍之內則用整數或浮點數輸出, 例如 :
>>> print('%g' % 123456) # 用 g 格式輸出整數
123456
>>> print('%g' % 123456.789) # 整數很大, 捨棄小數部分
123457
>>> print('%g' % 1234567) # 寬度較長時自動改為科學表示法
1.23457e+06
>>> print('%g' % 1234567.89) # 寬度較長時自動改為科學表示法
1.23457e+06
>>> print('%g' % 0.123456789)
0.123457
>>> print('%g' % 0.0123456789)
0.0123457
>>> print('%g' % 0.00123456789)
0.00123457
>>> print('%g' % 0.000123456789)
0.000123457
>>> print('%g' % 0.0000123456789) # 指數小於 -4 時自動改為科學表示法
1.23457e-05
>>> print('%G' % 0.123456789)
0.123457
>>> print('%G' % 0.0123456789)
0.0123457
>>> print('%G' % 0.00123456789)
0.00123457
>>> print('%G' % 0.000123456789)
0.000123457
>>> print('%G' % 0.0000123456789) # 寬度較長時自動改為科學表示法
1.23457E-05
(5). 可變寬度與精確度的用法 :
以上的範例中寬度與精確度格式均明確指定一個數值, 若用 * 字元取代明確的 m 與 .n則可以變數來控制這兩個格式, 這時後面的變數 tuple 中, 對應變數前面需傳入其寬度與精確度, 語法如下 (以輸出整數為例) :
'%[+]*.*d' % (width, precision, variable)
例如 :
>>> print('濕度 : %*d%%' % (5, 50))
濕度 : 50%
>>> print('濕度 : %0*d%%' % (5, 50))
濕度 : 00050%
>>> print('濕度 : %0*d%%' % (6, 50))
濕度 : 000050%
注意, * 格式指的是寬度, 其值必須為整數, 下面是可變寬度的範例 :
>>> print('溫度 : %*.2f' % (6, 28.435))
溫度 : 28.43
>>> print('溫度 : %0*.2f' % (6, 28.435))
溫度 : 028.43
>>> print('溫度 : %0*.2f' % (7, 28.435))
溫度 : 0028.43
下面是可變精確度範例 :
>>> print('溫度 : %6.*f' % (1, 28.435))
溫度 : 28.4
>>> print('溫度 : %6.*f' % (2, 28.435))
溫度 : 28.43
>>> print('溫度 : %6.*f' % (3, 28.435))
溫度 : 28.435
>>> print('溫度 : %6.*f' % (4, 28.435))
溫度 : 28.4350
下面是寬度與精確度同時可變的範例 :
>>> print('溫度 : %*.*f' % (6, 1, 28.435))
溫度 : 28.4
>>> print('溫度 : %*.*f' % (6, 2, 28.435))
溫度 : 28.43
>>> print('溫度 : %*.*f' % (6, 3, 28.435))
溫度 : 28.435
>>> print('溫度 : %0*.*f' % (7, 3, 28.435))
溫度 : 028.435
輸出多個可變寬度格式的範例如下 :
>>> print('溫度 : %0*.*f 濕度 : %0*d%%' % (6, 2, 28.435, 4, 50))
溫度 : 028.43 濕度 : 0050%
注意, 使用 * 可變寬度與精確度格式時, 傳入的 tuple 元素要一一對應.
2. 使用 format() 方法 :
此種方式是從 Python 3.0 開始支援的, 字串物件中多了一個 format() 方法來格式化要輸出的字串, 其語法除對應位置內嵌外, 還支援與位置無關的變數序號內嵌與關鍵字內嵌, 比傳統的 % 格式化更有彈性, 且繼承了 % 格式化字元用法 (除了對齊方式以外).
(1). 對應位置內嵌 :
此與傳統 % 格式化用法類似, 只不過把 % 換成 {} 而已, 語法如下 :
print("...{}...{}...".format(var1, var2, ...))
例如 :
>>> name='Tony'
>>> age=22
>>> print("name:{} age:{}".format(name, age)) # 將變數輸出到對應之 {}
name:Tony age:22
>>> str="name:{} age:{}"
>>> print(str.format(name, age))
name:Tony age:22
內嵌大括弧內可用冒號加上 <, ^, > , +, 0 等格式化字元對變數進行格式化, 語法如下 :
:[[填充]<|^|>|=][+][0][寬度][,][.精確度]型態
- 填充 : 若資料寬度比指定最小寬度小時用來填充空位的字元
- < : 靠左對齊
- ^ : 置中對齊
- > : 靠右對齊
- = : 在 +/- 號與數值間用填充字元補位 (僅限數值)
- + : 正數前面加上 + 號
- 0 : 寬度過多時空位補 0 (用於數值)
- 寬度 : 指定最小輸出寬度 (超出時不受此限制)
- , : 千位符號, 將整數部分每千位打一個逗號
- 精確度 : 指定浮點數精確度到小數點後幾位或輸出字串中的前幾個字元
- 型態 : 與 % 格式化之型態相同 (例如 d, f, s 等), 另新增二進制類型 b
這些格式化字元必須放在一個冒號之後. 比較特殊的是, format() 有更豐富的對齊格式, 可靠左, 置中, 與靠右對齊, 而且可在前面設定填充字元, 其優先權比補 0 高. 注意, 填充字元需搭配對齊格式, 不可單獨使用. 其次, format() 增加了一個千位符號格式 (即逗號) 以及二進制整數型態 b. 另外, 由於 format() 使用了大括弧 {} 內嵌, 輸出大括弧本身要用 {{ 與 }}.
% 格式化的 s 類型可用來輸出字串或數值, 例如 :
>>> print('%s' % ('Hello')) # s 型態本用來輸出字串
Hello
>>> print('%s' % (123)) # s 型態也可輸出數值 (整數)
123
>>> print('%s' % (3.14159)) # s 型態也可輸出數值 (浮點數)
3.14159
>>> print('%s' % (1.23e-9)) # s 型態也可輸出數值 (科學表示法)
1.23e-09
但 format() 格式化的 s 型態只能輸出字串, 不可用來輸出數值, 否則會報錯, 例如 :
>>> print('{:s}'.format('Hello')) # s 型態只能用來輸出字串
Hello
>>> print('{:s}'.format(123)) # s 型態不可用來輸出字數值
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
ValueError: Unknown format code 's' for object of type 'int'
>>> print('{:s}'.format(3.14159)) # s 型態不可用來輸出字數值
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
ValueError: Unknown format code 's' for object of type 'float'
>>> print('{:s}'.format(1.23e-9)) # s 型態不可用來輸出字數值
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
ValueError: Unknown format code 's' for object of type 'float'
當指定之寬度大於資料實際寬度時可設定對齊方式, format() 的對齊分別用 <, ^, 與 > 表示靠左, 置中, 與靠右對齊 (字串預設靠左, 數值預設靠右), 而傳統 % 格式化是預設靠右 (不論字串或數值預設皆靠右), 使用 - 字元控制靠左對齊 (無法置中), 所以 format() 的對其方式較有彈性, 例如 :
>>> print('|{:10d}|'.format(123)) # 數值預設靠右對齊
| 123|
>>> print('|{:<10d}|'.format(123)) # 指定靠左對齊
|123 |
>>> print('|{:^10d}|'.format(123)) # 指定置中對齊
| 123 |
>>> print('|{:>10d}|'.format(123)) # 指定靠右對齊
| 123|
>>> print('|{:10s}|'.format('Hello')) # 字串預設靠左對齊
|Hello |
>>> print('|{:<10s}|'.format('Hello')) # 指定靠左對齊
|Hello |
>>> print('|{:^10s}|'.format('Hello')) # 指定置中對齊
| Hello |
>>> print('|{:>10s}|'.format('Hello')) # 指定靠右對齊
| Hello|
對齊格式前面可指定填充字元, 當資料寬度小於指定寬度時, 空位就會用此填充字元補滿, 其優先權高於後面的補 0 格式, 亦即, 若輸出數值時同時指定填充字元與補 0, 則補 0 會被忽略. 填充字元對於製作標題或分隔行很方便, 例如 :
>>> print('{:=^20s}'.format('Hello World')) # 置中對齊空位以 = 填充
====Hello World=====
>>> print('{:*^20s}'.format('Hello World')) # 置中對齊空位以 * 填充
****Hello World*****
>>> print('{:=<20s}'.format('Hello World')) # 靠左對齊空位以 = 填充
Hello World=========
>>> print('{:=>20s}'.format('Hello World')) # 靠右對齊空位以 = 填充
=========Hello World
>>> print('{:#^20d}'.format(123)) # 置中對齊空位以 # 填充 (輸出數值)
########123#########
>>> print('{:#^020d}'.format(123)) # 置中對齊空位以 # 填 (補 0 無效)
########123#########
對於數值資料而言, 可用 = 對齊格式設定在 +/- 號與數值之間的空位用填充字元補位, 例如 :
>>> print('{:0=20d}'.format(123)) # 在 +/- 與數值間以 0 填充
00000000000000000123
>>> print('{:*=20d}'.format(123)) # 在 +/- 與數值間以 * 填充
*****************123
>>> print('{:=+20d}'.format(123)) # 在 +/- 與數值間以空格填充 (預設)
+ 123
>>> print('{:0=+20d}'.format(123)) # 在 +/- 與數值間以 0 填充 (正數)
+0000000000000000123
>>> print('{:0=+20d}'.format(-123)) # 在 +/- 與數值間以 0 填充 (負數)
-0000000000000000123
格式化字元 + 控制正數顯示 + 號, 例如 :
>>> print('{}'.format(123)) # 預設正數不顯示 + 號
123
>>> print('{:+}'.format(123)) # 指定正數顯示 + 號
+123
format() 方法對於整數新增了二進制類型 b, 以補 % 格式化之缺陷, 例如 :
>>> print('{:d}'.format(15)) # 輸出 10 進位整數
15
>>> print('{:x}'.format(15)) # 輸出 16 進位整數 (小寫)
f
>>> print('{:X}'.format(15)) # 輸出 16 進位整數 (大寫)
F
>>> print('{:o}'.format(15)) # 輸出 8 進位整數
17
>>> print('{:b}'.format(15)) # 輸出 2 進位整數
1111
>>> print('{:b}'.format(123)) # 輸出 2 進位整數
1111011
若資料寬度小於指定之最小寬度, 預設空位補空格, 但數值可用 0 格式指定補 0. 字串也可以補 0, 雖然較少會用到, 例如 :
>>> print('|{:^10d}|'.format(123)) # 預設空位補空格
| 123 |
>>> print('|{:^010d}|'.format(123)) # 指定空位補 0
|0001230000|
>>> print('|{:^010f}|'.format(123.45)) # 指定空位補 0 (浮點數補在小數)
|123.450000|
>>> print('|{:^010.2f}|'.format(123.45)) # 指定空位補 0 (浮點數整數小數均補 0)
|00123.4500|
>>> print('|{:^010s}|'.format('Hello'))
|00Hello000|
此處特地用 "^" 讓資料置中對齊, 且前後插入 "|" 字元以便觀察空位之補位情形, 可見對於浮點數而言, 沒有指定小數位數時, 0 會全部補在小數尾端; 有指定精確度, 且有空位時, 整數與小數部分會平均補 0.
format() 新增了千位符號格式, 其位置是在寬度格式後面, 例如 :
>>> print('{:,d}'.format(123456789))
123,456,789
>>> print('|{:09,d}|'.format(123456789)) # 沒有超過千位不補 0
|123,456,789|
>>> print('|{:010,d}|'.format(123456789)) # 沒有超過千位不補 0
|123,456,789|
>>> print('|{:011,d}|'.format(123456789)) # 沒有超過千位不補 0
|123,456,789|
>>> print('|{:012,d}|'.format(123456789)) # 超過千位才會補 0
|0,123,456,789|
精確度主要是用在浮點數與科學表示法, 以四捨五入方式顯示到指定之小數位數. 精確度也可以用在字串, 這時會輸出字串的前幾個字元, 例如 :
>>> print('圓周率={:.1f}'.format(3.1415926)) # 四捨五入到小數 1 位
圓周率=3.1
>>> print('圓周率={:.3f}'.format(3.1415926)) # 四捨五入到小數 3 位
圓周率=3.142
>>> print('{:.2e}'.format(0.123456789)) # 四捨五入到小數 2 位
1.23e-01
>>> print('{:.3e}'.format(0.123456789)) # 四捨五入到小數 3 位
1.235e-01
>>> print('{:.4e}'.format(0.123456789)) # 四捨五入到小數 4 位
1.2346e-01
>>> print('message={:.3s}'.format('Hello')) # 輸出字串中的前 3 字元
message=Hel
>>> print('message={:.7s}'.format('Hello')) # 輸出字串中的前 7 字元
message=Hello
若要輸出大括號本身, 需使用 {{ 與 }}, 例如 :
>>> print('集合 s={{{0}}}, {{{1}}}, {{{2}}}'.format(1, 2, 3))
集合 s={1}, {2}, {3}
此處 {{{0}}} 前面的 {{ 與後面的 }} 都是要輸出大括號本身 (集合符號), 中間的 {0} 才是內嵌要輸出的資料.
(2). 序號內嵌 :
除了上述對應位置內嵌外, 還可以在大括弧 {} 中填入序號 (0 起始) 來對應傳入 format() 之資料順序, 語法如下 :
print("...{1}...{0}...".format(a, b, ...))
此處 a 會被嵌入後面的 {0}, 而 b 則會被嵌入前面的 {1}.
格式化字串則依序放在冒號後面, 語法如下 :
print("...{0:格式化字串}...{1:格式化字串}...".format(a, b, ...))
例如 :
>>> temp=28.435
>>> humid=50
>>> print('溫度 : {0} 濕度 : {1}%'.format(temp, humid))
溫度 : 28.435 濕度 : 50%
>>> print('濕度 : {1}% 溫度 : {0}'.format(temp, humid)) # 序號調換
濕度 : 50% 溫度 : 28.435
>>> print('溫度 : {0:07.2f} 濕度 : {1:04d}%'.format(temp, humid))
溫度 : 0028.43 濕度 : 0050%
>>> print('溫度 : {0:+08.2f} 濕度 : {1:+06d}%'.format(temp, humid)) # 正數帶 + 號
溫度 : +0028.43 濕度 : +00050%
若傳入 format() 的引數是串列或元組, 序號後面可用 [] 存取序列中的元素來內嵌, 例如 :
>>> print('tuple : {0[0]}, {0[1]}, {0[2]}'.format((1, 2, 3)))
tuple : 1, 2, 3
>>> print('list : {0[0]}, {0[1]}, {0[2]}'.format([1, 2, 3]))
list : 1, 2, 3
(3). 關鍵字內嵌 :
也可以直接在 {} 中直接指定關鍵字來內嵌該變數, 語法如下 :
print("...{b}...{a}...".format(a=v1, b=v2, ...))
這樣就不需要煩惱序號對應的問題了.
格式化字串同樣放在冒號之後, 語法如下 :
print("...{b:格式化字串}...{a:格式化字串}...".format(a=v1, b=v2, ...))
例如 :
>>> temp=28.435
>>> humid=50
>>> print('溫度 : {temp} 濕度 : {humid}%'.format(temp=temp, humid=humid))
溫度 : 28.435 濕度 : 50%
>>> print('溫度 : {temp:07.2f} 濕度 : {humid:04d}%'.format(temp=temp, humid=humid))
溫度 : 0028.43 濕度 : 0050%
此種用法最有彈性, 但要注意 format() 裡面的傳入參數必須指定關鍵字, 不可只傳入變數, 否則會出現 KeyError 錯誤, 因為內嵌時找不到所需的關鍵字, 例如 :
>>> temp=28.435
>>> humid=50
>>> print('溫度 : {temp} 濕度 : {humid}%'.format(temp, humid))
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
KeyError: 'temp'
若傳入 format() 的引數是串列或元組, 關鍵字後面可用 [] 存取序列中的元素來內嵌, 例如 :
>>> print('tuple : {a[0]}, {a[1]}, {a[2]}'.format(a=(1, 2, 3)))
tuple : 1, 2, 3
>>> print('tuple : {a[0]}, {a[1]}, {a[2]}'.format(a=[1, 2, 3]))
tuple : 1, 2, 3
3. 使用 f 字串 :
f 字串是字串前面冠上一個 f 的格式化字串, Python 自 3.6 版開始支援這種字串格式化方式, 它可以將變數或運算式直接用 {} 內嵌到 f 字串中, 比 format() 更好用, 語法如下 :
print(f".....{var}.....{expression}.....")
其中 var 為變數, expression 為運算式.
Python 3.8 版又為 f 字串添加新功能, 在變數或運算式後面加一個 "=" 號將輸出變數名稱或運算式與等號, 這對程式偵錯相當方便, 語法如下 :
print(f".....{var=}.....{expression=}.....")
例如 :
>>> pi=3.14159
>>> r=5
>>> print(f'半徑={r}, 圓周長={2*pi*r}, 圓面積={pi*r*r}')
半徑=5, 圓周長=31.4159, 圓面積=78.53975
>>> print(f'{r=}, {2*pi*r=}, {pi*r*r=}')
r=5, 2*pi*r=31.4159, pi*r*r=78.53975
如果在 Python 3.8 之前的環境執行會出現語法錯誤, 例如 :
>>> print(f'{r=}, {2*pi*r=}, {pi*r*r=}')
File "<fstring>", line 1
(r=)
^
SyntaxError: invalid syntax
f 字串的格式化字元與前面 format() 中使用的完全一樣, 只要在變數或運算式後面加個冒號, 後面接著放置格式化字串即可, 語法如下 :
print(f".....{var:格式化字串}.....{expression:格式化字串}.....")
例如以 2, 8, 10, 16 進制輸出整數 :
>>> print(f'{15:d}') # 輸出 10 進位整數 (小寫)
15
>>> print(f'{15:x}') # 輸出 16 進位整數 (小寫)
f
>>> print(f'{15:X}') # 輸出 16 進位整數 (大寫)
F
>>> print(f'{15:o}') # 輸出 8 進位整數
17
>>> print(f'{15:b}') # 輸出 2 進位整數
1111
下面是空位補 0 的範例 :
>>> print(f'|{123:^10d}|') # 預設空位補空格
| 123 |
>>> print(f'|{123:^010d}|') # 指定空位補 0
|0001230000|
>>> print(f'|{123.45:^010f}|') # 指定空位補 0 (浮點數補在小數)
|123.450000|
>>> print(f'|{123.45:^010.2f}|') # 指定空位補 0 (浮點數整數小數均補 0)
|00123.4500|
在對齊格式前指定填充字元的範例如下 :
>>> print(f'{"Hello World":=<20s}') # 靠左對齊空位以 = 填充
Hello World=========
>>> print(f'{"Hello World":=^20s}') # 置中對齊空位以 = 填充
====Hello World=====
>>> print(f'{"Hello World":=>20s}') # 靠右對齊空位以 = 填充
=========Hello World
>>> print(f'{123:*^20d}') # 置中對齊空位以 * 填充
********123*********
>>> print(f'{123:*^020d}') # 置中對齊空位以 * 填充 (補 0 無效)
********123*********
下面是精確度格式的範例 :
>>> print(f'圓周率={3.1415926:.1f}') # 四捨五入到小數 1 位
圓周率=3.1
>>> print(f'圓周率={3.1415926:.3f}') # 四捨五入到小數 3 位
圓周率=3.142
>>> print(f'{0.123456789:.2e}') # 四捨五入到小數 2 位
1.23e-01
>>> print(f'{0.123456789:.3e}') # 四捨五入到小數 3 位
1.235e-01
>>> print(f'{0.123456789:.4e}') # 四捨五入到小數 4 位
1.2346e-01
>>> print(f'{"Hello":.3s}') # 輸出字串中的前 3 字元
Hel
>>> print(f'{"Hello":.7s}') # 輸出字串中的前 7 字元
Hello
注意, 此處因 f 字串使用了單引號, 故 Hello 外面要交替改用雙引號.
斷斷續續寫了三周終於把格式化測試完畢, 好累.
參考 :
# 字串格式化
沒有留言:
張貼留言