TL;DR - ISSUE 21118
The long Story
Josh Rosenberg发现 str.translate() 函数与 bytes.translate 相比非常慢,他提出issue,说明:
在Python 3中,str.translate()通常是性能悲观,而不是优化 .
为什么str.translate()慢?
str.translate() 非常慢的主要原因是查找曾经在Python字典中 .
maketrans 的使用使这个问题变得更糟 . 使用bytes的类似方法构建了一个包含256个项目的C数组来快速查找表 . 因此,使用更高级别的Python dict 会使Python 3.4中的 str.translate() 变得非常慢 .
现在发生了什么?
第一种方法是添加一个小补丁translate_writer,然而速度的提升并不令人满意 . 很快又测试了另一个补丁fast_translate,它产生了非常好的结果,加速率高达55% .
从文件中可以看出主要的变化是Python字典查找被更改为C级查找 .
现在的速度与 bytes 几乎相同
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
这里的一个小注意事项是性能增强仅在ASCII字符串中很突出 .
正如J.F.Sebastian在下面的comment中提到的,在3.5之前,翻译曾经以相同的方式用于ASCII和非ASCII情况 . 但是从3.5 ASCII情况下要快得多 .
早期的ASCII与非ascii过去几乎相同,但是现在我们可以看到性能的巨大变化 .
它可以是从71.6μs到2.33μs的改进,如answer所示 .
以下代码演示了这一点
python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop
python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop
制表结果:
Python 3.4 Python 3.5
Ascii 91.2 2.3
Unicode 101 117