f-string 格式化字符串 (Formatted String Literals)

1. 定义

f-string 是 Python 3.6+ 的字符串写法:在字符串前加 f,然后在 {} 里直接写变量或表达式,运行时自动替换成它的值。是目前拼接字符串、打印日志最推荐的方式。

name = "Alice"
age = 25
print(f"{name} is {age} years old")   # Alice is 25 years old

一句话:f"...{变量}..." = 把 {} 里的东西算出来,塞进字符串。+ 拼接和老式 % 格式化都清爽。

2. 拆解你的例子

print(f"lr={lr}: train_acc={train_acc_hist}, test_acc={test_acc_hist}")
片段含义
f"..."f-string,{} 里会被求值替换
lr=普通文本,原样打印(这个 lr= 是字符串字面量,不是代码)
{lr}变量 lr 的值被填进来
{train_acc_hist}变量 train_acc_hist 的值
: , 分隔用的普通文本

假设 lr=0.01train_acc_hist=0.95test_acc_hist=0.92,输出:

lr=0.01: train_acc=0.95, test_acc=0.92

注意:lr= 里的 lr你手打的文本{lr} 里的 lr 才是变量。两个 lr 一个是标签、一个是值,别搞混。

3. 格式说明符(: 后面控制显示)

{值:格式} —— 冒号后面控制怎么显示,训练日志里极常用:

acc = 0.9567
n = 1234567
 
f"{acc:.2f}"        # '0.96'      保留 2 位小数
f"{acc:.2%}"        # '95.67%'    百分比 + 2 位小数
f"{n:,}"            # '1,234,567' 千分位逗号
f"{acc:.4f}"        # '0.9567'    保留 4 位
f"{42:03d}"         # '042'       整数补 0 到 3 位
f"{acc:>10.2f}"     # '      0.96' 右对齐占 10 宽
f"{'hi':^8}"        # '   hi   '   居中占 8 宽
f"{n:.2e}"          # '1.23e+06'  科学计数法

训练日志建议给准确率/损失加 :.4f:.2%,否则 0.9567000000001 这种一长串很难看:

print(f"lr={lr}: train_acc={train_acc:.2%}, test_acc={test_acc:.2%}")
# lr=0.01: train_acc=95.67%, test_acc=92.30%

4. {} 里能放表达式(不只是变量)

f"{2 + 3}"                    # '5'         算术
f"{name.upper()}"             # 'ALICE'     调方法
f"{len(items)}"               # 列表长度
f"{arr.mean():.3f}"           # 表达式 + 格式化
f"{'yes' if ok else 'no'}"    # 三元表达式也行
f"{d['key']}"                 # 取字典值(注意引号别和外层冲突)

5. {var=} 调试神器(Python 3.8+)

变量名后加 =,会同时打印变量名和值,调试超方便:

lr = 0.01
print(f"{lr=}")               # lr=0.01   (自动带上 "lr=" 前缀!)
print(f"{train_acc=:.2%}")    # train_acc=95.67%

所以你的例子其实可以简写成:

print(f"{lr=}, {train_acc_hist=}, {test_acc_hist=}")

省得手打 lr=train_acc= 这些标签,变量名改了也不会对不上。

6. 和老式写法对比

name, age = "Alice", 25
 
# ① f-string(推荐)
f"{name} is {age}"
 
# ② str.format()(较老)
"{} is {}".format(name, age)
"{n} is {a}".format(n=name, a=age)
 
# ③ % 格式化(最老,类似 C 的 printf)
"%s is %d" % (name, age)
 
# ④ 直接 + 拼接(麻烦,还要手动转字符串)
name + " is " + str(age)
写法可读性备注
f-string最好Python 3.6+,首选
.format()老代码/需要延迟格式化时
%遗留写法,尽量别用
+ 拼接数字要 str(),易错

7. 常见坑

  • 忘了前面的 f"{lr}"(没 f)会原样打印 {lr} 而不是值——最常见的坑
  • 引号冲突:f-string 外层用双引号,里面取字典就用单引号 f"{d['k']}",别双引号套双引号
  • 大括号本身要打印:想输出字面的 {} 要写 {{}},如 f"{{{x}}}"{值}
  • {var=} 是 3.8+:老 Python 不支持,会报语法错误
  • 格式化用错类型f"{'abc':.2f}" 对字符串用 .2f 会报错,.2f 只对数字
  • f-string 里塞太复杂的逻辑:能算但可读性差,复杂计算先算好再放进去

8. 延伸阅读 / 关联概念

  • 列表推导式与简写 — 另一类高频”一行流”写法;见 list-comprehension-idioms.md
  • 格式说明符完整语法 — 对齐、填充、进制、精度等(Format Specification Mini-Language)
  • print() 参数sependflush 等控制输出行为
  • logging — 正式项目里比 print 更规范的日志方式
  • 官方文档:f-stringsFormat Spec