Python str.replace、re.sub与str.translate性能对比及选型建议

慢慢来
慢慢来
发布时间:2026-10-24| 9人浏览过
原创

Python 中做字符串替换最常用的三个工具是 str.replace、re.sub 和 str.translate。三者在底层实现、调用开销和擅长的替换模式上各不相同。本文通过具体场景和基准数据说明它们的性能差异,最后给出按场景选型的简要判断表。

一、三种方法的基本用法

1. str.replace

str.replace(old, new[, count]) 是最简单的字符串替换方法,将所有匹配的子串替换为新字符串,可选参数 count 限制替换次数。

text = "hello world, hello python"
result = text.replace("hello", "hi")
# 'hi world, hi python'

它是纯 C 实现的内置方法,不需要额外导入,调用开销最低。但它只能做固定字符串的精确匹配,不支持模式或条件替换。

2. re.sub

re.sub(pattern, repl, string, count=0, flags=0) 使用正则表达式匹配并替换。repl 可以是字符串,也可以是一个接收 match 对象的函数。

import re
text = "价格: 100元, 折扣: 20元"
result = re.sub(r'\d+', lambda m: str(int(m.group()) * 2), text)
# '价格: 200元, 折扣: 40元'

正则引擎的编译和匹配过程比固定字符串查找复杂得多,即使替换的是固定子串,re.sub 的开销也远高于 str.replace。但它能处理模式匹配、分组引用和动态替换,是三者中功能最强的。

3. str.translate

str.translate(table) 根据映射表对每个字符做一对一替换或删除。映射表通常用 str.maketrans 生成。

table = str.maketrans("aeiou", "12345")
text = "education"
result = text.translate(table)
# '2d5c1t34n'

它的特点是按单个字符查表替换,一次遍历就能完成多个字符的替换或删除。当需要同时替换大量不同的单字符时,str.translate 远快于多次调用 str.replace。但它只能处理字符级映射,不能替换子串。

Python str.replace、re.sub与str.translate性能对比及选型建议
图1:str.replace、re.sub 与 str.translate 的核心特征对比

二、性能差异的根本原因

三者之间的性能差异不是简单的"谁快谁慢",而是取决于替换任务的类型。理解底层机制才能做出正确选择。

str.replace 为什么最快

str.replace 的实现在 CPython 中是纯 C 代码。它使用优化的子串搜索算法(基于 Boyer-Moore 和 Horspool 的变体)直接扫描字节,找到匹配后复制替换内容到新字符串。整个过程没有正则编译、没有 Python 层函数调用、没有字符映射查表,是三者中路径最短的。

re.sub 的开销来自哪里

re.sub 每次调用时需要经历:正则表达式编译(如果没有预编译)→ 构建有限自动机 → 逐步匹配输入字符串 → 对每个匹配构建 match 对象 → 执行替换。即使正则表达式就是一个固定字符串,这些步骤也不会跳过。与 str.replace 相比,固定字符串替换场景下 re.sub 通常慢 5 到 10 倍。

预编译(re.compile)可以省去重复编译的开销。在循环中反复使用同一个正则时,预编译是必要的优化。但即使预编译后,匹配过程本身仍然比固定字符串搜索慢。

str.translate 快在哪里

str.translate 对字符串做单次线性遍历,对每个字符查一次映射表(本质上是字典查找或数组索引),决定替换、删除还是保留。当需要同时替换 10 个不同字符时,str.translate 只遍历一次字符串,而用 str.replace 逐个替换则需要遍历 10 次。替换的字符种类越多,str.translate 的优势越明显。

三、基准测试对比

以下测试使用 Python 3.11,在一段包含 10000 个字符的文本上分别执行替换操作,用 timeit 取 10000 次执行的平均耗时。

场景 1:替换单个固定子串

将文本中所有的 "Python" 替换为 "Java"。

import timeit

text = "Python is great. " * 500  # 约9000字符

# str.replace
t1 = timeit.timeit(lambda: text.replace("Python", "Java"), number=10000)

# re.sub
import re
pattern = re.compile(r"Python")
t2 = timeit.timeit(lambda: pattern.sub("Java", text), number=10000)

# 示例结果
# str.replace:  0.18s
# re.sub:       1.02s

str.replace 约为 re.sub 速度的 5.7 倍。这是 str.replace 最擅长的场景。str.translate 不适用于子串替换,此场景不参与对比。

场景 2:同时替换多个单字符

将文本中的元音字母 a、e、i、o、u 全部删除。

text = "education is the most powerful weapon" * 250

# str.replace 链式调用
def replace_chain(s):
    for ch in "aeiou":
        s = s.replace(ch, "")
    return s
t1 = timeit.timeit(lambda: replace_chain(text), number=10000)

# str.translate
table = str.maketrans("", "", "aeiou")
t2 = timeit.timeit(lambda: text.translate(table), number=10000)

# re.sub
pattern = re.compile(r"[aeiou]")
t3 = timeit.timeit(lambda: pattern.sub("", text), number=10000)

# 示例结果
# str.replace(×5):  0.95s
# str.translate:     0.22s
# re.sub:            1.85s

str.translate 比链式 str.replace 快约 4.3 倍,比 re.sub 快约 8.4 倍。需要同时替换或删除的字符越多,str.translate 的优势越大。

场景 3:基于模式的动态替换

将文本中所有数字序列翻倍。

text = "item1 costs 50, item2 costs 120, total 170" * 200

pattern = re.compile(r"\d+")
t1 = timeit.timeit(
    lambda: pattern.sub(lambda m: str(int(m.group()) * 2), text),
    number=10000
)

# 示例结果
# re.sub:  3.45s

这种场景只有 re.sub 能完成。str.replace 无法做模式匹配,str.translate 无法处理子串或动态逻辑。

Python str.replace、re.sub与str.translate性能对比及选型建议
图2:三种场景下 str.replace、re.sub、str.translate 的耗时对比

四、容易踩的性能陷阱

陷阱 1:用 re.sub 做固定字符串替换

这是最常见的性能浪费。很多人习惯导入 re 后对所有替换都使用 re.sub,但当替换目标是固定字符串时,str.replace 在各种文本长度下都明显更快。只有当替换涉及模式匹配(通配符、字符类、量词等),re.sub 的额外开销才值得付出。

陷阱 2:链式 str.replace 替换大量字符

需要替换 20 个不同的标点符号时,用 20 次 str.replace 链式调用意味着字符串被遍历 20 次,每次都生成一个新的字符串对象。改用 str.translate 只需一次遍历。

# 不推荐:链式 str.replace
def clean_punctuation(text):
    for ch in ',.;:!?()[]{}@#&*':
        text = text.replace(ch, '')
    return text

# 推荐:str.translate
remove_table = str.maketrans('', '', ',.;:!?()[]{}@#&*')
def clean_punctuation(text):
    return text.translate(remove_table)

陷阱 3:循环内反复 re.compile

虽然 Python 的 re 模块内部有编译缓存(默认缓存最近 512 个模式),但在性能敏感的场景下,显式预编译仍然更可靠。

# 不推荐
for line in lines:
    result = re.sub(r'\d{4}-\d{2}-\d{2}', 'DATE', line)

# 推荐
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
for line in lines:
    result = date_pattern.sub('DATE', line)

陷阱 4:误用 str.translate 处理子串

str.translate 只能做字符到字符的映射,不能把 "abc" 这个子串替换为 "xyz"——它会把 a、b、c 分别映射为 x、y、z。如果需要替换多字符子串,必须使用 str.replace 或 re.sub。

Python str.replace、re.sub与str.translate性能对比及选型建议
图3:根据替换需求选择方法的决策流程

五、进阶对比:预编译与文本长度的影响

预编译对 re.sub 的提升

不预编译时,re.sub 每次调用都要编译正则。对于简单模式,编译开销约占总耗时的 15%–30%。预编译后这部分开销只发生一次。但即使预编译,re.sub 处理固定字符串替换仍然比 str.replace 慢数倍,因为匹配引擎本身的开销无法消除。

文本长度的影响

三种方法的耗时都与文本长度近似线性增长,但斜率不同。对于极短字符串(几十个字符),三者差异不大,因为函数调用本身的固定开销占主导。当字符串长度超过几千字符后,底层扫描效率的差异开始显现,str.replace 和 str.translate 的优势变得明显。

特殊场景:大量不同子串替换

如果需要替换几十种不同的子串(不是单字符),str.replace 的链式调用效率会随替换种类线性下降。这时可以考虑用 re.sub 结合合并后的正则模式和字典映射:

replacements = {"apple": "苹果", "banana": "香蕉", "cherry": "樱桃"}
pattern = re.compile("|".join(re.escape(k) for k in replacements))
result = pattern.sub(lambda m: replacements[m.group()], text)

这种方式只遍历一次字符串,当替换种类超过 5–10 种时,通常比链式 str.replace 更快。

六、选型建议总结

场景推荐方法原因
替换一个或几个固定子串str.replace开销最低,代码最简单
删除或替换多种单字符str.translate一次遍历完成全部映射
模式匹配替换re.sub唯一支持正则的选项
动态替换逻辑(函数作为 repl)re.subrepl 参数接受回调函数
大量不同子串替换(>5种)re.sub + 合并模式避免多次遍历
性能不敏感的简单脚本任意差异可忽略,选最易读的
实际选择时,代码可读性和维护性同样重要。如果替换操作不在热路径上(不是每秒执行成千上万次),三种方法的性能差异对程序整体运行时间的影响微乎其微。优先选择意图最清晰的写法,只在性能分析确认瓶颈后再做针对性优化。
Python str.replace、re.sub与str.translate性能对比及选型建议
图4:字符串替换方法选型总结
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。