- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
为什么在 Python 中,replace
比 translate
快 1.5 倍?
In [188]: s = '1 a 2'
In [189]: s.replace(' ','')
Out[189]: '1a2'
In [190]: s.translate(None,' ')
Out[190]: '1a2'
In [191]: %timeit s.replace(' ','')
1000000 loops, best of 3: 399 ns per loop
In [192]: %timeit s.translate(None,' ')
1000000 loops, best of 3: 614 ns per loop
最佳答案
假设使用 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 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 <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__
表明有一个翻译表在起作用,而 replace 只提到旧到新的子字符串替换。
求助老哥们dis
提示:
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,
和replace_delete_single_character :
/* 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
中运行得更快。
感谢您提出这个问题。
关于Python str.translate VS str.替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31143290/
你信吗?我有一个这样的循环(请原谅任何错误,我不得不大量编辑大量信息和变量名称,相信我它有效)。 ...旧示例已删除,请参见下面的代码... 如果我将那些中间的 str = "Blah\(odat.c
我正在做一个本地测试来比较 C# 中 String 和 StringBuilder 的 Replace 操作性能,但是对于 String 我使用了以下代码: String str = "String
我想知道为什么str += "A"和 str = str + "A"有不同的表现。 在实践中, string str = "cool" for(int i = 0; i approximately
我有一个类型列表 [("['106.52.116.101']", 1), ("['45.136.108.85']", 1)] 并想将其转换为 [('106.52.116.101', 1), ('45.
我有一个类型列表 [("['106.52.116.101']", 1), ("['45.136.108.85']", 1)] 并想将其转换为 [('106.52.116.101', 1), ('45.
我正在遍历 HashMap并通过一些本地变量中的模式匹配将值放入其中。 委托(delegate)者 fn lyrics_no_bottles(song_template:&mut String){
如果字符串(短语)中只有元音,它(对我而言)说True;否则说 False。我不明白为什么它总是返回 False,因为 (x >= x) 总是返回 True。我感谢任何人检查此查询的解决方案。 (st
我有代码以某种方式转换字符串引用,例如取第一个字母 trait Tr { fn trim_indent(self) -> Self; } impl Tr for &'a str { f
我正在学习指针,这是我的代码。我定义了一个指向 char(实际上是字符串)的指针 *str 和一个指向 int *a 的指针,它们的定义方式相同。我认为 str 和 a 都应该是一个地址,但是当我试图
为什么我会收到错误消息?我已经正确添加了类型,对吗? Invalid index type "str" for "Union[str, Dict[str, str]]"; expected type
你知道下面两个函数是否等价吗? function validate(str) { return ( ['null','','undefined'].indexOf(str) [v, valida
我正在解决这里的 Dataquest 问题:https://app.dataquest.io/m/293/data-cleaning-basics/5/removing-non-digit-chara
我有一个字符串列表,如下所示: ["A TB", "A-R TB", "B TB", "B-R TB", "C TB", "C-R TB"...] 但字符串的顺序是随机的。我如何编写一个将元素配对的函
我正在尝试将此函数从使用 split 改为使用 str.extract (正则表达式)。 def bull_lev(x): spl = x.rsplit(None, 2)[-2].strip(
给定这样的数据结构: [{'a':1, 'b': 2}, {'c':3 }, {'a':4, 'c':9}, {'d':0}, {'d': 0, 'b':6}] 目标是解析数据以产生: {'a': 2
给定这样的数据结构: [{'a':1, 'b': 2}, {'c':3 }, {'a':4, 'c':9}, {'d':0}, {'d': 0, 'b':6}] 目标是解析数据以产生: {'a': 2
s = 'someString' s = QTreeWidgetItem(s) print(s.text(0)) # 0 being 'column' 输出: 's' 如果我对另一
黑白有什么区别: function(char* str ) function(char* str[] ) function(char str[] ) 它们是如何被调用的(通过什么类型的string/c
我试过谷歌搜索但找不到准确的答案,所以请允许我尝试在这里提问。如果问题看起来不合适,请告诉我,我会删除它。 在 JS 中,您可以通过三种不同的方式编写特定的内置功能: 字符串长度 str.toStri
我有这段代码(我的 strlen 函数) size_t slen(const char *str) { size_t len = 0; while (*str) {
我是一名优秀的程序员,十分优秀!