Python 新式格式化方法(.format() 和 f-string),与旧式 % 格式化
🧭 一、Python 字符串格式化的三种主流方式
| 名称 | 写法示例 | 引入版本 | 特点 |
|---|---|---|---|
| 旧式格式化 | "%.2f" % pi | Python 1.x | 简洁但功能有限,类似 C 语言 |
.format() 方法 | "{:.2f}".format(pi) | Python 2.6+ | 更灵活,支持位置、命名、对齐等 |
| f-string(字面量格式化) | f"{pi:.2f}" | Python 3.6+ | 最简洁、高效、可读性强,现代推荐写法 |
下面我们重点讲解 新写法(.format() 和 f-string) 的语法,并与 % 对照。
🔧 二、新写法的核心语法:{[name][!r/s/a][:format_spec]}
我们简化为最常用的形式:
{变量名:格式说明}其中 格式说明(format_spec) 的通用结构是:
[[fill]align][sign][#][0][width][.precision][type]看起来复杂?别怕!我们只关注你关心的部分:宽度(width)、精度(precision)、类型(type)
对应关系如下:
| 功能 | % 写法 | .format() / f-string 写法 |
|---|---|---|
| 字符串截断 + 宽度 | %10.5s | {:.5s} 或 {:10.5s} |
| 浮点数保留2位小数 | %.2f | {:.2f} |
| 浮点数总宽8位、保留2位 | %8.2f | {:8.2f} |
| 整数补零到5位 | %05d 或 %.5d | {:05d} |
| 左对齐 | %-10s | {: <10} 或 {:<10} |
✅ 注意:新写法中,对齐符号是显式的:
<:左对齐(默认字符串)>:右对齐(默认数字)^:居中对齐=:符号在前,数字在后(用于正负号)
📚 三、详细对照表 + 示例
1️⃣ 字符串格式化(控制显示长度和宽度)
| 需求 | % 写法 | .format() | f-string |
|---|---|---|---|
| 显示前5个字符 | %.5s | {:.5s} | f"{s:.5s}" |
| 总宽10,右对齐,最多5字符 | %10.5s | {:10.5s} | f"{s:10.5s}" |
| 总宽10,左对齐 | %-10.5s | {: <10.5s} 或 {:<10.5s} | f"{s:<10.5s}" |
s = "Hello, Python!"
print("%10.5s" % s) # ' Hello'
print("{:10.5s}".format(s)) # ' Hello'
print(f"{s:10.5s}") # ' Hello'
print("%-10.5s" % s) # 'Hello '
print(f"{s:<10.5s}") # 'Hello '2️⃣ 浮点数格式化(控制小数位和总宽度)
| 需求 | % 写法 | f-string |
|---|---|---|
| 保留2位小数 | %.2f | f"{x:.2f}" |
| 总宽8,保留2位,右对齐 | %8.2f | f"{x:8.2f}" |
| 用0填充,总宽8 | %08.2f | f"{x:08.2f}" |
| 左对齐 | %-8.2f | f"{x:<8.2f}" |
x = 3.14159
print("%8.2f" % x) # ' 3.14'
print(f"{x:8.2f}") # ' 3.14'
print("%08.2f" % x) # '00003.14'
print(f"{x:08.2f}") # '00003.14'
print("%-8.2f" % x) # '3.14 '
print(f"{x:<8.2f}") # '3.14 '✅ 注意:新写法中,0 填充直接写成 08,不需要额外 flag。
3️⃣ 整数格式化(补零、宽度)
| 需求 | % 写法 | f-string |
|---|---|---|
| 至少5位,不足补0 | %.5d 或 %05d | f"{n:05d}" |
| 总宽8,数字至少5位 | %8.5d | f"{n:8.05d}" ❌ 不行!✅ 正确:先保证5位 → f"{n:05d}" 再整体控制宽度需分步或用嵌套 |
⚠️ 注意:新写法中,不能直接写成{:8.5d},因为整数没有“精度”概念。
正确做法是:用0填充指定宽度即可。
n = 42
print("%.5d" % n) # '00042'
print(f"{n:05d}") # '00042'
print("%8.5d" % n) # ' 00042'
print(f"{n:8d}".replace(' ', '0') if len(str(n)) < 5 else ...) # 复杂!
# 更好的方式:先格式化数字位数,再整体对齐(通常不需要这么复杂)
print(f"{n:05d}".rjust(8)) # ' 00042'💡 实际开发中,整数补零用 {:0Nd} 就够了,很少需要同时控制“数字位数”和“总宽度”。
🆚 四、新旧写法对比总结
| 维度 | % 格式化 | .format() / f-string |
|---|---|---|
| 可读性 | 较差(符号多) | 高(结构清晰) |
| 灵活性 | 有限 | 极强(支持命名、表达式、对象属性等) |
| 性能 | 一般 | f-string 是最快的 |
| 错误提示 | 模糊(如类型不匹配报错难懂) | 更友好 |
| 功能扩展 | 不支持自定义格式 | 支持 __format__ 协议 |
| 是否推荐 | ❌ 仅用于兼容老代码 | ✅ f-string 是现代 Python 首选 |
✅ 推荐使用 f-string 的理由:
- 直接嵌入变量:
f"Hello {name}" - 支持表达式:
f"平方是 {x**2}" - 支持格式:
f"{price:.2f}" - 性能最优(编译时处理)
🧪 五、实战建议:什么时候用哪种?
| 场景 | 推荐写法 |
|---|---|
| 学习/写新项目 | f-string(f"{x:.2f}") |
| 阅读/维护老代码 | 理解 % 格式 |
| 需要动态格式模板(如从配置读取) | .format()(因为 f-string 不能动态改格式字符串) |
| 简单日志打印 | f-string 足够 |
🎁 六、附:常见格式速查表(f-string 版)
x = 123.4567
s = "Python"
n = 42
# 浮点数
f"{x:.2f}" # '123.46'
f"{x:10.2f}" # ' 123.46'
f"{x:010.2f}" # '0000123.46'
f"{x:<10.2f}" # '123.46 '
# 字符串
f"{s:.4s}" # 'Pyth'
f"{s:>10.4s}" # ' Pyth'
# 整数
f"{n:05d}" # '00042'
f"{n:>8d}" # ' 42'