假设Python 2.7(因为我不得不在没有声明的情况下掷硬币),我们可以在string.py中找到string.translate和string.replace的源代码:>>> 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 code you see here isn't normally used nowadays.
Beginning with Python 1.6, many of these functions are implemented as
methods on the standard string object.
我投了你一票,因为你是从分析开始的,所以让我们继续往下讲:from cProfile import run
from string import ascii_letters
s = '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 :8(_replace)
1 0.000 0.000 2.059 2.059 :1()
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 :12(_translate)
1 0.000 0.000 1.785 1.785 :1()
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__表示有一个翻译表在运行,而replace只提到从旧到新的子字符串替换。
让我们向我们的老朋友^{}寻求提示:from dis import dis
替换:def dis_replace():
'1 a 2'.replace(' ', '')
dis(dis_replace)
dis("'1 a 2'.replace(' ', '')")
3 0 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)
2 0 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)。
这是source for translate。
如果您查看注释,可以看到基于输入的长度有多个replace函数定义行。
我们的子串替换选项是:/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
Py_LOCAL(PyStringObject *)
replace_substring_in_place(PyStringObject *self,/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
Py_LOCAL(PyStringObject *)
replace_substring(PyStringObject *self,/* Special case for deleting a single character */
/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
Py_LOCAL(PyStringObject *)
replace_delete_single_character(PyStringObject *self,
char from_c, Py_ssize_t maxcount)
'1 a 2'.replace(' ', '')是len(self)==6,用空字符串替换1个字符,使其成为replace_delete_single_character。
您可以自己检查函数体,但答案是“对于这个特定输入,C函数体在replace_delete_single_character中的运行速度比string_translate快。
谢谢你问这个问题。