Python 比较startswith()的速度与。在()
我的印象是Python 比较startswith()的速度与。在(),python,performance,python-3.x,time,Python,Performance,Python 3.x,Time,我的印象是startswith必须比中的更快,原因很简单,中的必须进行更多的检查(允许正在查找的单词位于字符串中的任何位置)。但是我有我的怀疑,所以我决定timeit。下面给出了计时代码,您可能会注意到,我没有做太多计时工作;代码相当简单 import timeit setup1=''' def in_test(sent, word): if word in sent: return True else: return False ''' se
startswith
必须比中的更快,原因很简单,中的必须进行更多的检查(允许正在查找的单词位于字符串中的任何位置)。但是我有我的怀疑,所以我决定timeit
。下面给出了计时代码,您可能会注意到,我没有做太多计时工作;代码相当简单
import timeit
setup1='''
def in_test(sent, word):
if word in sent:
return True
else:
return False
'''
setup2='''
def startswith_test(sent, word):
if sent.startswith(word):
return True
else:
return False
'''
print(timeit.timeit('in_test("this is a standard sentence", "this")', setup=setup1))
print(timeit.timeit('startswith_test("this is a standard sentence", "this")', setup=setup2))
结果:
>> in: 0.11912814951705597
>> startswith: 0.22812353561129417
因此,startswith
的速度是原来的两倍!。。鉴于我在上面所说的,我觉得这种行为非常令人费解。我对这两个的计时是否有问题,或者中的确实更快了?若然,原因为何
请注意,即使它们都返回False
,结果也非常相似(在这种情况下,
中的必须实际遍历整个句子,以防它之前短路):
如果I必须从头开始实现这两个函数,它看起来会像这样(伪代码):
startswith
:开始逐个比较单词字母和句子字母,直到a)单词耗尽(返回True)或b)检查返回False(返回False)
在
中:对于在句子中可以找到单词首字母的每个位置,调用开始
我就是不明白
只是想说明一下,
中的和的startswith
是不相等的;我只是在说一个例子,一个人试图查找的单词必须是字符串中的第一个。这是因为你必须查找并调用一个方法<中的code>是专门化的,并直接导致比较操作(调用它,依次调用PySequence\u Contains
),而str.startswith
则通过较慢的字节码:
2 LOAD_ATTR 0 (startswith)
4 LOAD_FAST 1 (word)
6 CALL_FUNCTION 1 # the slow part
将
中的
替换为
中的
。\uuuuu包含
,强制对该情况进行函数调用,这几乎抵消了速度差:
setup1='''
def in_test(sent, word):
if sent.__contains__(word):
return True
else:
return False
'''
以及时间安排:
print(timeit.timeit('in_test("this is a standard sentence", "this")', setup=setup1))
print(timeit.timeit('startswith_test("this is a standard sentence", "this")', setup=setup2))
0.43849368393421173
0.4993997460696846
中的之所以在这里获胜,是因为它不需要经过整个函数调用设置,而且它提供了有利的案例 您正在比较字符串上的运算符与属性查找和函数调用。第二个会有更高的开销,即使第一个会占用大量数据的很长时间
此外,您正在查找第一个单词,因此如果它确实匹配,
中的将查看与startswith()相同的数据。要查看差异,您应该查看悲观情况(未找到结果,或字符串末尾匹配):
如果查看函数生成的字节码:
>>> dis.dis(in_test)
2 0 LOAD_FAST 1 (word)
3 LOAD_FAST 0 (sent)
6 COMPARE_OP 6 (in)
9 POP_JUMP_IF_FALSE 16
3 12 LOAD_CONST 1 (True)
15 RETURN_VALUE
5 >> 16 LOAD_CONST 2 (False)
19 RETURN_VALUE
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
您会注意到有很多开销与字符串匹配没有直接关系。在更简单的函数上执行测试:
def in_test(sent, word):
return word in sent
将更加可靠。谢谢您的回答。悲观案例已经在编辑的帖子上了。你的悲观案例很短。看4个字符-vs-40只是一个舍入错误。看看4-vs-4000,你就会发现其中的区别。我理解,但我想用其中的任何一个来检查像这样的小句子,而不是整个文本。但是现在它确实更有意义了。所以我们可以说,in
是O(n),而startswith
是O(c),但是对于小的n
So(n)更好,对吗?确切地说:)就是这样,有利的情况似乎没有这么大的影响;悲观的情况产生了同样的结果。更像字符串的长度和startswith
的开销,我应该更详细@Ev.Kounis:-)长度就是我所说的有利情况。事实上,在一个小字符串中是否存在匹配不会产生太大的差异。现在我们回到同一页xD
>>> dis.dis(in_test)
2 0 LOAD_FAST 1 (word)
3 LOAD_FAST 0 (sent)
6 COMPARE_OP 6 (in)
9 POP_JUMP_IF_FALSE 16
3 12 LOAD_CONST 1 (True)
15 RETURN_VALUE
5 >> 16 LOAD_CONST 2 (False)
19 RETURN_VALUE
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
def in_test(sent, word):
return word in sent