f-string 的 = 语法是 Python 3.8+ 内置的变量名与值自动展开功能,如 f"{x=}" 输出 "x=42",非 debug 模式,无需配置;支持格式化、表达式,但仅展开字面量,不递归解析嵌套对象。

f-string 的 = 语法是核心,不是“debug模式”而是内置调试快捷写法
Python 3.8+ 直接支持在 f-string 中用 = 自动展开变量名和值,比如 f"{x=}" 会输出 "x=42"。这不是某种需启用的 debug 模式,而是 f-string 的原生语法糖,无需导入、无需配置。
常见错误是漏掉等号后的 =,写成 f"{x}" 就只输出值;或者误以为要加引号或括号,比如 f"{x=} "(末尾空格不影响),但 f"{(x)=}" 或 f"{'x'}={x}" 就失去自动命名意义。
-
f"{x=}"→ 输出"x=123" -
f"{x=!r}"→ 输出"x=123"(对字符串会带引号:"s='hello'") -
f"{x=:.2f}"→ 输出"x=123.00"(格式化仍生效) - 支持表达式:
f"{len(s)=}"→ 输出"len(s)=5",但注意表达式名可能不直观(如f"{s.upper()=}"输出"s.upper()='HELLO'")
多变量一行打印时,空格和换行会影响可读性,建议分开展开
虽然可以写 f"{a=}, {b=}, {c=}",但当变量值较长或含换行符时,输出容易混乱,且无法对齐。实际调试中更推荐每变量独立一行,用换行符增强可读性。
注意:f-string 内部不能直接换行,但可以用括号隐式续行,或用三引号拼接 —— 后者更清晰:
立即学习“Python免费学习笔记(深入)”;
f"""
{a=}
{b=}
{items[0]=}
"""这样输出天然带换行,也方便快速注释某一行(比如临时删掉 {items[0]=} 这行)。
- 避免
f"{a=}, {b=}, {very_long_dict=}"—— 值太长会导致单行溢出,难以定位 - 如果变量名本身是动态的(如循环中的
key),f"{key}={d[key]}"是唯一办法,=语法无法替代 -
=展开的是左侧“字面量”,所以f"{x + 1=}"输出的是"x + 1=43",不是"x=42"
与 pprint 或日志结合时,别混淆 = 和格式化目标
想把 x=123 这种字符串传给 logging.debug() 或 pprint.pprint(),直接拼接即可。但要注意:f-string 的 = 只作用于当前字符串,不会改变变量本身,也不会触发额外求值(和普通 f-string 一样,只计算一次)。
性能上无额外开销,但若在高频循环里大量使用(如每轮都 f"{huge_list=}"),会因字符串构建和 repr 调用产生可观开销 —— 此时应考虑条件打印或改用 if DEBUG: print(...) 包裹。
- 正确:
logger.debug(f"before sort: {data=}") - 错误:
pprint(f"{data=}")—— 这会打印字符串"data=[...]",而不是美化data本身;应写成pprint({"data": data})或直接pprint(data) - 调试嵌套结构时,
=不会展开深层,比如f"{user.profile=}"仍只调用profile.__repr__(),不会自动 pprint 其内容
旧版本 Python(=,替代方案要手动重复变量名
低于 3.8 的环境(比如某些 CentOS 系统自带的 Python 3.6),f"{x=}" 会报 SyntaxError: f-string: invalid syntax。此时只能退回到显式写法,但可以封装一个轻量函数减少重复:
def var(x, name=None):
if name is None:
import inspect
frame = inspect.currentframe().f_back
name = [k for k, v in frame.f_locals.items() if v is x][0]
return f"{name}={x!r}"
<h1>使用:print(var(my_list))</h1>不过这个方案有缺陷:依赖 inspect、不支持表达式、在优化模式(-O)下可能失效、且无法获取全局变量名。最稳妥的做法仍是升级 Python 版本,或接受手动写 f"x={x}"。
- 不要用
sys._getframe()替代inspect.currentframe()—— 它更不稳定,且被明确标记为内部 API - 线上环境禁用
inspect很常见,这种调试函数只适合本地开发 - 如果必须兼容老版本又想要类似体验,
pip install icecream的ic()是更健壮的选择,但它属于第三方,不属于“原生 f-string”范畴
调试时真正省时间的,不是语法多炫,而是能一眼看出「这是哪个变量、值是否符合预期」——= 语法刚好卡在这个点上,但它的边界也很清楚:不处理嵌套、不控制深度、不替代真正的调试器。



















