优先用 f"" 进行一次性拼接,可读性好且性能不输;循环多次拼接应改用 list.append() + join(),避免 + 导致 o(n²) 时间复杂度;str.format() 和 % 已过时,f"" 更快更安全。

字符串拼接用 + 还是 f""?看场景,别无脑换
Python 3.6+ 里 f"" 确实写起来爽,但不是所有情况都比 + 快。关键看拼接次数和字符串长度:单次拼接(比如日志里插一个变量),f"" 和 + 几乎没差别;但循环里反复拼接,用 + 就是灾难——因为字符串不可变,每次 + 都要新建对象、复制全部内容。
- 场景一:一次性拼接(如
f"User {name} logged in")→ 优先用f"",可读性好,性能不输 - 场景二:动态构建长文本(如生成 HTML 模板、CSV 行),且拼接次数 > 10 → 改用
list.append()+" ".join() - 错误现象:
s = ""然后在 for 循环里s += item→ 时间复杂度 O(n²),10 万次拼接可能卡住
str.join() 为什么比 + 快?它到底做了什么
str.join() 不是“边加边分配”,而是先遍历一次所有元素算总长度,再一次性申请内存,最后把各段拷贝进去。这是 C 层优化过的路径,绕过了 Python 层反复构造字符串对象的开销。
- 必须传入可迭代对象,不能直接传一堆参数:
"-".join(a, b, c)是错的,得写成"-".join([a, b, c])或"-".join((a, b, c)) - 如果元素不是字符串,
join()会直接报TypeError: sequence item 0: expected str instance, int found,得提前转:map(str, numbers) - 空列表
[]传给join()返回空字符串,安全;但None会直接报错
格式化函数 str.format() 和 % 已过时,但还有人在用
str.format() 在 3.6 前是主力,现在除了兼容旧代码,基本没理由选它。性能上比 f"" 慢 20%~40%,因为要解析格式字符串、匹配占位符、再替换——而 f"" 是编译期就确定表达式,运行时只求值。
-
"{} {}".format(a, b)和f"{a} {b}"功能等价,后者更快更直观 -
%格式化(如"%s %d" % (s, n))不仅慢,还容易出错:类型不匹配时不报错但结果异常(比如%d遇到None抛TypeError) - 唯一例外:需要延迟格式化(比如日志库中传入未求值的格式串),才保留
str.format或f""的惰性包装,但那是高级用法,日常不用管
拼接含大量 Unicode 或 emoji 的字符串时,要注意编码边界
Python 字符串是 Unicode,但底层存储用 UTF-8 编码的字节序列做缓冲。当拼接包含代理对(surrogate pair)的 emoji(如 ?、??)时,f"" 和 + 行为一致,没问题;但如果你手动切片或用正则处理拼接结果,就可能在代理对中间断开,导致乱码。
立即学习“Python免费学习笔记(深入)”;
- 不要用
s[5:10]去截取含 emoji 的字符串做显示裁剪,改用grapheme库或unicodedata检查字符边界 -
len()返回的是 Unicode 码点数,不是字节数;s.encode("utf-8")才是真实字节长度,网络传输或写文件前记得确认 - 这个坑和拼接方式无关,但很多人在优化拼接时顺手加截断逻辑,结果埋了隐性 bug











