前置知识: 零基础起步

字符串格式化:把值变成好看的文字

4 min入门

以打印一张设备状态报表为场景,一次学会 f-string 格式说明符:小数位、千分位、百分比、对齐补零与调试专用的 {x=};顺带说清 str.format 与 % 风格如今还活在哪里。

前置知识

读过 基本数据类型,知道 f-string 是「引号前加 f,大括号里放变量」;用过 变量与常量 里的赋值。

场景:一行报表逼出的格式需求

你在给 ESP32 玩具设备做巡检脚本(作者项目 FoloToy-calendar 就要干这个),从接口拿到原始数据,想打印一行人能读的状态:

python
device = {"name": "bedroom-01", "uptime_s": 987654, "battery": 0.873, "fw": "2.3.1"}

print(f"{device['name']}  运行 {device['uptime_s']}s  电量 {device['battery']}  固件 {device['fw']}")
text
bedroom-01  运行 987654s  电量 0.873  固件 2.3.1

三个毛病:电量是 0.873 想显示 87.3%;987654 秒数没有千分位,数位要靠手数;名字一长整行就错位,没法竖着扫。这些都不是计算问题,是格式化问题——f-string 冒号后面的「格式说明符」就是为此存在的。

动手做:五分钟把报表改像样

python
device = {"name": "bedroom-01", "uptime_s": 987654, "battery": 0.873, "fw": "2.3.1"}

name = f"{device['name']:<12}"        # 左对齐,占 12 格
up = f"{device['uptime_s']:,}"        # 千分位
bat = f"{device['battery']:.1%}"      # 乘 100 加 %,保留 1 位小数

print(f"{name}  运行 {up:>9}s  电量 {bat:>6}  固件 {device['fw']}")
text
bedroom-01    运行   987,654s  电量  87.3%  固件 2.3.1

规则一条就能推导所有写法:{值:填充 对齐 宽度, 分组. 精度 类型}。不背全表,先记最常用的五招:

写法含义示例输出
{x:.2f}保留 2 位小数f"{3.14159:.2f}"3.14
{x:,}千分位逗号f"{987654:,}"987,654
{x:.1%}百分比(自动乘 100)f"{0.873:.1%}"87.3%
{x:>8}右对齐占 8 格f"{7:>8}"' 7'
{x:04d}补零到 4 位f"{42:04d}"0042

对齐符号三个方向:< 左、> 右、^ 居中;数字默认右对齐、字符串默认左对齐,所以给数字写 :>9 往往是显式声明而非必须。

为什么是这样

冒号后那串字符不是 f-string 发明的语法,而是标准库的格式说明迷你语言(Format Specification Mini-Language),str.format() 与 f-string 共用同一套。三个方法的关系按 2026 年的实务排序:

  • f-string(首选):Python 3.6 引入,3.12 起(PEP 701)连引号嵌套、换行表达式都放开了,没有理由再用别的;
  • str.format():模板字符串存成变量、多处复用时仍顺手:tpl = "{name} 得 {score}",之后 tpl.format(name="小明", score=85);
  • % 风格:新代码不写,但日志里还大量存在且是推荐写法——logger.debug("处理 %s", data) 的延迟格式化能省性能(原因见 日志),读老代码也躲不开。

坑点实录

坑一:中文对不齐。宽度按「字符个数」算,中文一个字也只占 1 格,但显示宽度是 2,混排报表照样歪。标准库没有内置解法,要么全英文排版,要么用第三方 wcwidth 算显示宽度再手动补格。

坑二:{x:.2f} 不能喂给字符串。f"{'abc':.2f}" 抛 ValueError: Unknown format code 'f' for object of type 'str'——报错里的 'f' 就是类型码,读到这句先检查值的类型。

坑三:说明符内部的顺序写反。迷你语言各段有固定次序:对齐、宽度、千分位、精度、类型,即 :>10,.2f 这种形状。写成 f"{987654:>,10}" 会报 ValueError——千分位 , 必须排在宽度之后:f"{987654:>10,}" 输出 ' 987,654'。

坑四:调试时懒得拆 print。3.8 起有个专用语法,等号会同时打印变量名和值:

python
hp = 86.54321
print(f"{hp=}")            # hp=86.54321
print(f"{hp = :.1f}")      # hp = 86.5(等号两侧空格会保留,仍可用格式符)
text
hp=86.54321
hp = 86.5

自我检查

  • 不查表能写出:两位小数、千分位、百分比、右对齐占 10 格;
  • 能说出 % 风格在什么场景仍是推荐(日志延迟格式化);
  • 知道中文对不齐的原因(宽度按字符数而非显示宽度);
  • 能用 {x=} 一次打印变量名与值。

小练习

  1. 预测题:f"{0.07:.0%}" 输出什么?先写答案再运行(注意四舍五入)。
  2. 修改题:把本文报表扩一列 rssi(信号强度,整数,负数如 -67),要求右对齐占 6 格,负数自然带符号。
  3. 实战题:写函数 money(cents: int) -> str,输入分、输出元,如 money(12345) 得 "123.45";补一条断言 assert money(5) == "0.05",体会补零与精度怎么配合。

下一步