字符串拼接慢是因为str不可变,每次+或+=都新建对象并复制内容,10000次产生大量中间字符串和内存开销;io.StringIO通过可增长缓冲区实现追加写入,避免重复拷贝,适用于循环多次写入后一次性取值的场景。

为什么字符串拼接慢,而 io.StringIO 能提速
Python 中用 + 或 += 拼接字符串时,每次都会新建对象——因为 str 是不可变类型。拼接 10000 次,就可能产生上万个中间字符串,触发大量内存分配与垃圾回收。而 io.StringIO 底层维护一个可增长的缓冲区(类似 list),写入只是追加操作,避免重复拷贝。
什么时候该换用 io.StringIO
适用于循环内多次写入、最终只取一次完整结果的场景,比如生成 HTML 片段、日志批量组装、CSV 行拼接等。不适用于单次拼接或仅两三个字符串组合——此时 ''.join() 或 f-string 更轻量。
- 循环体中调用
+=超过 ~10 次,就值得考虑替换 - 拼接内容来自变量或函数返回值(非字面量),
join()不易提前收集列表时,StringIO更灵活 - 需要中途插入换行、缩进或条件写入(如
write()+writeln()风格),比维护 list 再 join 更直观
io.StringIO 的正确用法和常见错误
别直接用 str() 强转 StringIO 对象——它不是字符串,而是文件类对象。必须调用 .getvalue() 获取结果;用完建议显式 .close()(尤其在长生命周期对象中,防止缓冲区驻留)。
import io
<h1>✅ 正确:写入后取值</h1><p>buf = io.StringIO()
for i in range(1000):
buf.write(f"item-{i},")
result = buf.getvalue() # ← 关键!不是 str(buf)
buf.close()</p><h1>❌ 错误:str(buf) 返回的是对象描述,不是内容</h1><h1>str(buf) → "<_io.StringIO object at 0x...>"- 不要在循环外反复创建/销毁
StringIO实例——复用更高效 - 如果只是拼接固定几项,用
''.join([a, b, c])仍比StringIO快 -
StringIO默认编码为 Unicode,无需指定 encoding;若需字节流,用io.BytesIO
性能对比:真实差距有多大
在 CPython 3.9+ 下,10 万次短字符串拼接,StringIO 通常比 += 快 5–20 倍,比 list.append() + ''.join() 慢 10–30%(因方法调用开销略高)。但可读性与控制力更强——比如你可以在写入前做格式化、跳过空值、动态缩进。
立即学习“Python免费学习笔记(深入)”;
- 纯性能优先:用
list+join - 逻辑复杂、写入模式不规则:用
StringIO - 注意:PyPy 下
+=有优化,差距会缩小,但StringIO依然稳定
真正容易被忽略的是缓冲区残留——没调用 .getvalue() 就丢弃对象,内容就丢了;或者忘了 .close() 导致小对象长期占内存。这不是 bug,但会让性能优化白费。



















