f-string在Python 3.6+中通常比+快,但循环内使用、含函数调用或重载__str__的对象会显著变慢;少量字面量拼接+更优;大量拼接必须用str.join();注意版本兼容性与类型安全。

字符串拼接用 + 还是 f-string?
Python 3.6+ 中,f-string 几乎总是比 + 快,尤其在多变量、嵌套表达式场景下。但关键不是“快多少”,而是“什么时候会意外变慢”——比如把 f-string 写在循环里却没意识到它每次都要解析格式占位符。
-
+在拼接少量字面量(如"a" + "b" + "c")时,CPython 会静态优化成单个字符串,实际无开销 -
f-string在运行时求值,如果里面调用函数(如f"{expensive_func()}"),每次拼接都执行,容易成为性能瓶颈 -
%格式和.format()已不推荐:语法冗长、参数校验开销大、且.format()在 Python 3.12 前有额外对象创建成本
大量拼接(如构建日志、HTML 片段)该用 str.join()
当你要把几十上百个字符串连起来,+ 或 f-string 会触发多次内存分配和复制,时间复杂度接近 O(n²);而 str.join() 是单次预分配 + 一次拷贝,O(n) 稳定。
- 错误写法:
result = ""然后循环result += item—— 这是典型“二次方陷阱” - 正确做法:先收集到列表(
parts.append(item)),最后"\n".join(parts) - 注意:
str.join()要求所有元素都是str,混入int或None会直接报TypeError: sequence item 0: expected str instance
f-string 的隐式转换和 __str__ 调用开销
f-string 对每个表达式默认调用 str(),这看似方便,实则可能触发意外行为或性能损耗——特别是对象重载了 __str__ 但没缓存结果时。
- 例如对一个自定义类实例
f"{obj}",若其__str__每次都做 IO 或计算,拼接 1000 次就等于调用 1000 次 - 若你只需要 ID 或字段值,显式写
f"{obj.id}"更安全、更快 -
!r和!s修饰符(如f"{obj!r}")也会触发对应方法调用,不是零成本
跨 Python 版本兼容性:别在 3.5- 环境硬上 f-string
3.6 才引入 f-string,低版本会直接语法错误 SyntaxError: invalid syntax。CI 或旧服务环境里踩过这个坑的人不少。
立即学习“Python免费学习笔记(深入)”;
- 如果必须支持 3.5,用
.format()是最稳妥的降级方案(%格式虽快但类型检查弱,易出错) - 工具链中(如 pre-commit、tox)务必验证目标 Python 版本是否真能跑通
f-string,光看文档不够 - 某些打包工具(如 PyInstaller 旧版)在分析 AST 时对
f-string支持不全,可能漏掉依赖或报奇怪的NameError
真正影响性能的往往不是拼接语法本身,而是你没意识到表达式被重复求值、类型没对齐、或者根本没做批量预处理。写完一行拼接,顺手想想它会在什么上下文中被调多少次。











