Kodewick
第 24 课,共 31 课目录

字符串格式化

第 24 课,共 31 课 · 第 4 部分 · 代码和数据 · 约 15 分钟

第 2 课就用上了 f-string,第 3 课用过 :.2f。那个冒号后面其实是一套小语法,叫格式说明符:小数位、分隔符、宽度、对齐都由它管,而值本身不变。这一课一样一样地讲,最后排一张整齐的表。

格式说明符

花括号里,前面是值,冒号后面是格式说明符:{值:说明符}。说明符只改值显示的样子。

main.py
1price = 1234567.8912print(f"{price}")3print(f"{price:.2f}")4print(f"{price:.0f}")5print(f"{price:,.2f}")6print(f"{price:_.2f}")
输出
1234567.891
1234567.89
1234568
1,234,567.89
1_234_567.89

.2f 是「定点小数,保留两位」。前面加逗号,就每三位加一个千分位逗号;换成下划线,就用 _ 分隔。整数也能用:f"{5000000:,}" 得到 5,000,000。

最后写一个 %,就把小数显示成百分比:先乘 100,再加上百分号,小数位照你写的来。

main.py
1done = 72total = 83print(f"{done / total:%}")4print(f"{done / total:.1%}")5print(f"{done / total:.0%}")
输出
87.500000%
87.5%
88%
先猜一猜

这行会显示什么?

1print(f"{2 / 3:.0%}")

宽度、对齐和填充

说明符里的一个数是宽度:最少占几个字符。值不够长,就用空格补上。下面两边的竖线标出每个值从哪开始、到哪结束。

main.py
1print(f"|{'oil':8}|")2print(f"|{42:8}|")3print(f"|{'oil':>8}|")4print(f"|{'oil':^8}|")5print(f"|{42:<8}|")6print(f"|{'lighthouse':4}|")
输出
|oil     |
|      42|
|     oil|
|  oil   |
|42      |
|lighthouse|

文字默认靠左,数字默认靠右。<、>、^ 分别是靠左、靠右、居中。宽度只是「最少」:'lighthouse' 比 4 长,就整个显示出来。

在对齐符号前面放一个字符,就用它代替空格来补,这叫填充字符。

main.py
1print(f"{'库存':*^15}")2print(f"{'灯油':.<12}340")3print(f"{7:0>3}")4print(f"{7:03}")5print(f"{-7:05}")
输出
******库存*******
灯油..........340
007
007
-0007

0>3 是在左边补 0。数字还有个简写:宽度前面直接写 0,比如 03,也是补 0,而且负号会留在最前面。

正负号和其他进制

默认只有负数带符号。+ 让正数也带上 +;写一个空格,正数前面留一个空位,正数负数就能对齐。

main.py
1print(f"{5:+} {-5:+}")2print(f"{5: } {-5: }")3print(f"{255:b} {255:o} {255:x} {255:X}")4print(f"{255:#x} {255:#b}")5print(f"{5:08b}")6print(f"{1234567:.2e}")
输出
+5 -5
 5 -5
11111111 377 ff FF
0xff 0b11111111
00000101
1.23e+06
字母显示成255 变成
b二进制11111111
o八进制377
x / X十六进制ff / FF
e科学计数法2.550000e+02

# 加上 Python 代码里用的前缀(0x、0b、0o)。几部分的顺序是固定的:填充和对齐、正负号、#、0、宽度、分隔符、.小数位、字母。08b 就是「补 0 到 8 位,用二进制」。

排一张整齐的表

表头和每一行,同一列用同样的宽度和对齐,列就对齐了。一般文字列靠左,数字列靠右。

main.py
1stock = [("lamps", 12, 1.5), ("oil", 340, 0.25), ("wicks", 5, 12.0)]2print(f"{'Item':<8}{'Qty':>6}{'Price':>8}")3print("-" * 22)4for name, qty, price in stock:5    print(f"{name:<8}{qty:>6}{price:>8.2f}")
输出
Item       Qty   Price
----------------------
lamps       12    1.50
oil        340    0.25
wicks        5   12.00

表头不用小数,但宽度一样:8、6、8。每一行的单价多加了 .2f,小数点也对齐了。这里的名字特意用了英文,原因见下面的小技巧。点单步,看每一行是怎么拼出来的。

小技巧: 宽度按字符个数算,一个汉字算 1 个,可屏幕上一个汉字差不多有两个英文字母宽。所以带汉字的表格,代码没错也可能对不齐。

用 = 调试

在表达式后面加 =,f-string 会显示表达式本身、一个等号和它的值。想看看一个变量里装的是什么,这样最快。

main.py
1lamps = 122name = "Wick"3share = 2 / 34print(f"{lamps=}")5print(f"{name=}")6print(f"{lamps * 3 = }")7print(f"{share=:.2f}")
输出
lamps=12
name='Wick'
lamps * 3 = 36
share=0.67

字符串会带着引号显示,多了个空格一眼就能看出来。= 两边的空格会原样留在输出里;要加说明符,照样写在冒号后面。

宽度用变量

宽度和小数位也可以来自变量:在说明符里再套一对花括号。

main.py
1names = ["oil", "lamps", "lighthouse"]2w = max([len(n) for n in names])3for n in names:4    print(f"{n:>{w}}|")5digits = 36print(f"{3.14159:.{digits}f}")
输出
       oil|
     lamps|
lighthouse|
3.142

这里最长的名字决定宽度,列表里换什么名字,都排得下。

老写法

别人的代码里还会看到两种老写法。format() 和 str.format 的说明符和 f-string 是同一套;% 有自己的一套,写法相近,比如 %.2f、%5d。

main.py
1print(format(1234.5, ",.2f"))2print("{}有{}盏灯".format("Wick", 12))3print("{0}、{1}、{0}".format("开", "关"))4print("{name:>6}|".format(name="oil"))5print("%s有%d盏灯" % ("Wick", 12))6print("%.2f 和 %5d|" % (3.14159, 42))
输出
1,234.50
Wick有12盏灯
开、关、开
   oil|
Wick有12盏灯
3.14 和    42|
写法例子
f-string(推荐)f"{x:.2f}"
format() 函数format(x, ".2f")
str.format"{:.2f}".format(x)
% 运算符"%.2f" % x

format(值, 说明符) 排一个值。str.format 按顺序填每个 {},也可以按编号或名字填。% 是最老的:%s 放任何值,%d 放整数,%.2f 放小数,值不止一个时用元组。写新代码,f-string 最短也最清楚。

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

一大笔钱

把合计显示成带千分位、两位小数的样子。

要显示
合计:¥1,234,567.89
exercise1.py
1total = 1234567.8912print(f"合计:¥{total}")
输出
点「运行」或按 Ctrl+Enter
练习 2

进度

显示 完成:,后面跟着完成了多少,用保留一位小数的百分比。

要显示
完成:87.5%
exercise2.py
1done = 72total = 83print(done, total)
输出
点「运行」或按 Ctrl+Enter
练习 3

星号标题

让 title 在一行星号中间居中。宽度用 width,改了它,这一行跟着变。

要显示
****库存****
exercise3.py
1title = "库存"2width = 103print(title)
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • {值:说明符} 只改值显示的样子。
  • .2f 定小数位,, 或 _ 加千分位,% 显示百分比。
  • 一个数定宽度;< > ^ 定对齐;它们前面的字符是填充;03 补 0。
  • + 或空格管正负号;b、o、x、e 显示其他进制和科学计数法。
  • 表头和每行用同样的宽度,表格就对齐了。
  • f"{x=}" 显示表达式和它的值,调试很方便。
  • {n:>{w}} 让宽度来自变量。
  • format() 和 str.format 是老写法,说明符一样;% 用相近的写法,比如 %.2f。