假设Python
2.7版(因为我要掷硬币而不会被说),我们可以找到源代码string.translate并与string.replace在
string.py:
>>> import inspect>>> import string>>> inspect.getsourcefile(string.translate)'/usr/local/Cellar/python/2.7.9/frameworks/Python.framework/Versions/2.7/lib/python2.7/string.py'>>> inspect.getsourcefile(string.replace)'/usr/local/Cellar/python/2.7.9/frameworks/Python.framework/Versions/2.7/lib/python2.7/string.py'>>>
哦,我们不能,
as string.py开始于:
"""A collection of string operations (most are no longer used).Warning: most of the pre you see here isn't normally used nowadays.Beginning with Python 1.6, many of these functions are implemented asmethods on the standard string object.
我投票给您,是因为您开始进行概要分析,所以让我们继续进行下去:
from cProfile import runfrom string import ascii_letterss = '1 a 2'def _replace(): for x in range(5000000): s.replace(' ', '')def _translate(): for x in range(5000000): s.translate(None, ' ')替换:
run("_replace()") 5000004 function calls in 2.059 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.976 0.976 2.059 2.059 <ipython-input-3-9253b3223cde>:8(_replace) 1 0.000 0.000 2.059 2.059 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 5000000 1.033 0.000 1.033 0.000 {method 'replace' of 'str' objects} 1 0.050 0.050 0.050 0.050 {range}对于翻译:
run("_translate()") 5000004 function calls in 1.785 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.977 0.977 1.785 1.785 <ipython-input-3-9253b3223cde>:12(_translate) 1 0.000 0.000 1.785 1.785 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 5000000 0.756 0.000 0.756 0.000 {method 'translate' of 'str' objects} 1 0.052 0.052 0.052 0.052 {range}我们的函数调用次数是相同的,不是更多的函数调用意味着运行会变慢,但是通常是一个不错的选择。有趣的是,
translate在我的机器上运行速度比
replace!考虑到测试并不孤立变化的乐趣-
这不是问题,因为我们只关心能告诉为什么 会 出现差异。
无论如何,至少现在我们知道可能存在性能差异,并且在评估字符串对象的方法时确实存在性能差异(请参阅参考资料
tottime)。这
translate
__docstring__表明有一个转换表在起作用,而替换仅提及旧到新的子字符串替换。
让我们转向老朋友
dis的提示:
from dis import dis
更换:
def dis_replace(): '1 a 2'.replace(' ', '')dis(dis_replace)dis("'1 a 2'.replace(' ', '')") 30 LOAD_ConST 1 ('1 a 2') 3 LOAD_ATTR 0 (replace) 6 LOAD_ConST 2 (' ') 9 LOAD_ConST 3 ('') 12 CALL_FUNCTION 2 15 POP_TOP 16 LOAD_ConST 0 (None) 19 RETURN_VALUE和
translate,对我来说运行速度更快:
def dis_translate(): '1 a 2'.translate(None, ' ')dis(dis_translate) 20 LOAD_ConST 1 ('1 a 2') 3 LOAD_ATTR 0 (translate) 6 LOAD_ConST 0 (None) 9 LOAD_ConST 2 (' ') 12 CALL_FUNCTION 2 15 POP_TOP 16 LOAD_ConST 0 (None) 19 RETURN_VALUE不幸的是,两者看起来与相同
dis,这意味着我们应该在这里开始寻找字符串的C源代码(通过转到我现在正在使用的Python版本的python源代码找到)](https://
hg。
python.org/cpython/file/a887ce8611d2/Objects/stringobject.c)。
这是translation的来源。
如果查看注释,则可以看到
replace基于输入长度的多个函数定义行。
我们的子字符串替换选项包括:
replace_substring_in_place
Py_LOCAL(PyStringObject *)replace_substring_in_place(PyStringObject *self,
和replace_substring:
Py_LOCAL(PyStringObject *)replace_substring(PyStringObject *self,
和replace_delete_single_character:
Py_LOCAL(PyStringObject *)replace_delete_single_character(PyStringObject *self, char from_c, Py_ssize_t maxcount)
'1 a 2'.replace(' ', '')是len(self)== 6,用一个空字符串替换1个char,使其成为areplace_delete_single_character。
您可以自己检查函数体,但是答案是“
C函数体的运行速度
replace_delete_single_character比
string_translate此特定输入要快。
感谢您提出这个问题。



