我试图在Python 3.4中使用 text.translate()
从给定的字符串中删除不需要的字符 .
最小的代码是:
import sys
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))
它按预期工作 . 但是,在Python 3.4和Python 3.5中执行相同的程序会产生很大的差异 .
计算时间的代码是
python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); " "s.translate(mapper)"
Python 3.4程序需要 1.3ms 而Python 3.5中的相同程序只需 26.4μs .
与Python 3.4相比,Python 3.5有哪些改进使其更快?
1 回答
TL;DR - ISSUE 21118
The long Story
Josh Rosenberg发现
str.translate()
函数与bytes.translate
相比非常慢,他提出issue,说明:为什么str.translate()慢?
str.translate()
非常慢的主要原因是查找曾经在Python字典中 .maketrans
的使用使这个问题变得更糟 . 使用bytes的类似方法构建了一个包含256个项目的C数组来快速查找表 . 因此,使用更高级别的Pythondict
会使Python 3.4中的str.translate()
变得非常慢 .现在发生了什么?
第一种方法是添加一个小补丁translate_writer,然而速度的提升并不令人满意 . 很快又测试了另一个补丁fast_translate,它产生了非常好的结果,加速率高达55% .
从文件中可以看出主要的变化是Python字典查找被更改为C级查找 .
现在的速度与
bytes
几乎相同这里的一个小注意事项是性能增强仅在ASCII字符串中很突出 .
正如J.F.Sebastian在下面的comment中提到的,在3.5之前,翻译曾经以相同的方式用于ASCII和非ASCII情况 . 但是从3.5 ASCII情况下要快得多 .
早期的ASCII与非ascii过去几乎相同,但是现在我们可以看到性能的巨大变化 .
它可以是从71.6μs到2.33μs的改进,如answer所示 .
以下代码演示了这一点
制表结果: