前面 字符串基础与常用方法 和 输入输出与格式化字符串 都提过 f-string,但那只是入门。字符串格式化是 Python 里最需要”知道更多”的话题之一——你以为你会写 f"{x:.2f}",但一遇到”数字千分位加两位小数”、”日期时间”、”补零对齐”、”表达式调试”,就抓瞎了。这一篇把三种格式化姿势(f-string、str.format、%)的语法一次讲透,重点是 format-spec 迷你语言——这才是格式化的”内核”。
一、三代格式化
新代码请用 f-string,其他两代只用于阅读老代码:
1 | name, age = "咖飞", 3 |
三者共享的”格式规范”
无论哪种方式,冒号后面的部分(format spec) 都是同一套迷你语言:
1 | "{:.2f}".format(3.14159) # '3.14' |
学好 format spec 是关键。
二、format spec 完整语法
格式规范的完整语法(简化版):
1 | [[fill]align][sign][#][0][width][,_][.precision][type] |
- fill:填充字符(默认为空格);
- align:对齐
<(左)、>(右,数字默认)、^(居中)、=(数字符号后填充); - sign:
+(正数显示 +)、-(默认,只显示负号)、(正数留空格); - #:显示进制前缀(0x、0b、0o);
- 0:数字用 0 填充;
- width:最小总宽度;
- , 或 _:千分位分隔符;
- .precision:小数位数或字符串截断长度;
- type:
d/b/o/x/X(进制)、f/e/g(浮点)、s(字符串)、%(百分比)。
三、宽度与对齐
1 | f"{42:5d}" # ' 42' 默认右对齐 |
四、补零
1 | f"{7:04d}" # '0007' 4 位宽度,前补 0 |
五、小数位与千分位
1 | f"{3.14159:.2f}" # '3.14' |
六、百分比
1 | f"{0.256:.1%}" # '25.6%' |
% 会自动 *100 并加百分号,非常方便。
七、进制
1 | f"{255:b}" # '11111111' |
八、正负号
1 | f"{3:+}" # '+3' |
九、字符串格式化
1 | f"{'py':10}" # 'py ' 默认左对齐 |
十、日期时间
datetime、date、time 都支持 strftime 格式:
1 | from datetime import datetime, date |
十一、动态宽度和精度
宽度、精度可以是变量:
1 | w = 10 |
十二、= 调试语法(Python 3.8+)
f-string 的”表达式调试神器”:
1 | x, y = 42, 10 |
以前需要 print("x =", x),现在 f-string 直接搞定,是最实用的现代 Python 语法之一。
十三、r 和 !r 强制 repr
1 | name = "咖飞" |
!r 在打印/日志里非常有用——能明显区分字符串和数字。
十四、嵌套 f-string
f-string 里可以嵌套 f-string,但要小心引号冲突:
1 | name = "咖飞" |
十五、str.format 的独有能力
format 版本在从外部读格式模板时优于 f-string(因为 f-string 是编译期解析):
1 | template = "{name} 得了 {score} 分" |
f-string 里也能做属性和索引访问,只是不能”延迟求值”。
十六、% 老式格式化
只在维护老代码时会用到:
1 | "%s is %d years old" % ("咖飞", 3) |
新代码请一律用 f-string。
十七、Locale 与国际化
想要”按当前地区规则显示数字”(比如欧洲用 . 做千分位):
1 | import locale |
标准的 , 千分位是”美式”,locale 提供跨地区支持。
十八、一个综合例子:账单打印
1 | # invoice.py |
输出效果整齐对齐:
1 | 咖飞小店 |
十九、常见陷阱
- f-string 内的引号冲突(3.11 之前):
f"{d["key"]}"→ 报错。改成d['key']。 - 忘了
f前缀:"{name}"只是字面串,不会替换。 {}字面:想输出{,写{{`;`}}。- 格式化 None:
f"{None:.2f}"会报错,先判空或转字符串。 %s后面变量个数不匹配:"%s %s" % ("a",)会 TypeError。f-string 没这个问题。str.format(**d)里 key 是数字或有非法字符:得用位置或format_map。- 精度对整数无效:
f"{100:.2f}"会输出100.00(自动转 float),但f"{100:.2d}"报错——d是整数格式,不接受精度。
二十、小结与延伸阅读
- 新代码永远用 f-string;模板从外部读时用
str.format(); - 冒号后面是 format spec 迷你语言:宽度、对齐、填充、千分位、精度、进制;
%系列被 f-string 全面取代,只出现在老代码;=调试语法、!r强制 repr、日期时间%Y-%m-%d都要掌握;- Python 3.12 前 f-string 内引号有限制;
- 千分位用
,,百分比用.1%,日期用 strftime 语法。
延伸阅读:
- Format Spec Mini-Language:https://docs.python.org/zh-cn/3/library/string.html#format-specification-mini-language
- PEP 498 f-string:https://peps.python.org/pep-0498/
- PEP 701 f-string 语法扩展(Python 3.12):https://peps.python.org/pep-0701/
下一篇 序列切片深入解析 我们要把 Python 切片的门道彻底讲清。