s.find()和s.index()哪个更快?(涉及IT技术)

7
现在我理解了Python中s.find()s.index()之间的区别,感谢这个问题,我想知道哪种方法更快?
除了必须在try / except中使用s.index()可能会导致潜在开销之外,速度上是否有任何显著差异?

就时间复杂度(大O符号)而言,这两者是等价的。 - Willem Van Onsem
我理解它们可能使用类似的算法 - 如果不是完全相同的话,只是在输出上有所不同,但我只是想知道是否存在明显的性能差异。 - YeO
如果你想知道什么更快,就用 timeit - Wombatz
2个回答

10
除了潜在的开销,如果我们必须在try/except中包含`s.index()` ,在速度方面是否有任何显着差异?
至少在(C)Python中,`find`,`index`,`rfind`,`rindex`都是内部函数any_find_slice的包装器。实现是相同的,唯一的区别是,如果`index`和`rindex`找不到结果,则会为您引发一个`ValueError`。如果你继续计时它们,你会看到它们之间没有明显的有意义的区别。
➜  ~ python -m perf timeit -s "s = 'a' * 1000 + 'b'" "s.find('b')"
Median +- std dev: 399 ns +- 7 ns
➜  ~ python -m perf timeit -s "s = 'a' * 1000 + 'b'" "s.index('b')"
Median +- std dev: 396 ns +- 3 ns

我在这里使用perf进行计时。

我猜其他 Python 实现的情况应该是相同的。两种方法都执行相同的操作,只有在请求的元素未被找到时它们的反应略有不同。


谢谢,所以它们在内部确实是完全相同的函数。那么我想就不应该有任何明显的速度/性能差异了... - YeO
@YeO 通常需要防范使用 str.index 抛出的异常,但这是唯一会使其变慢的事情。除此之外,它们做的事情是相同的。 - Dimitris Fasarakis Hilliard
1
只想补充一下,在这两个档案中,子字符串被找到了,所以没有实质性的区别。当子字符串未被找到时,两者之间存在很大的差异(索引慢得多)。 - augustomen

1
@Dimitris的回答显示,如果找到了子字符串,s.find()s.index()的性能相当好。
但是正如@augustomen指出的那样,如果找不到子字符串,由于异常处理,s.index()的速度会明显变慢。我们可以使用以下代码片段进行测试。
请注意,我使用的是与@Dimitris不同的机器,因此无法将我的时间与他的进行比较。
$ python3 -m timeit -s "s = 'a' * 1000" "s.find('b')"
5000000 loops, best of 5: 87.3 nsec per loop

$ python3 -m timeit -s "s = 'a' * 1000" "try: s.index('b')" "except ValueError: pass"
1000000 loops, best of 5: 242 nsec per loop

很明显,当子字符串未找到时,s.find()是胜利者,但这只是因为我们没有为其添加try/except块吗?
让我们尝试为s.find()添加一个try/except块(尽管我们知道它不会被触发)。
$ python3 -m timeit -s "s = 'a' * 1000" "try: s.find('b')" "except ValueError: pass"
5000000 loops, best of 5: 89.1 nsec per loop

我们在这里看到,仅仅存在一个try/except块几乎不会改变时间。只有当异常实际触发时,我们才会遭受到有意义的性能损失。
故事的寓意是,如果有合理的机会找不到子字符串,那么请使用s.find()
如果你确信子字符串几乎总能找到,那么你可以使用s.find()s.index()。在这种情况下,你可能更喜欢使用s.index(),因为try/except语法向其他开发人员表明,你正在处理一个不太可能经常发生的边缘情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接