为什么tuple.index()在性能上与list.index()相似?

时间:2014-05-14 21:34:36

标签: python python-2.7

我编写了一个简单的函数,它接收一些实现.index()的函数和一个要检查的字符列表。

我的假设是,由于字符串和元组都是不可变的,因此它们具有相似的性能(或者至少,元组的性能会超过列表)。相反,元组似乎等同于列表。那是为什么?

from string import ascii_lowercase
from random import randint
from timeit import Timer


def check_index(st, guesses):
    for i in guesses:
        st.index(i)

if __name__ == "__main__":
    num_checks = 10
    lst = [n for n in ascii_lowercase]
    st = ascii_lowercase
    tup = tuple(lst)
    guesses = [ascii_lowercase[randint(0, len(ascii_lowercase)-1)]
               for n in xrange(num_checks)]

    def run_string():
        check_index(st, guesses)

    def run_list():
        check_index(lst, guesses)

    def run_tuple():
        check_index(tup, guesses)

    t2 = Timer(run_list)
    print "List", t2.timeit()
    t3 = Timer(run_tuple)
    print "Tuple", t3.timeit()
    t = Timer(run_string)
    print "String", t.timeit()

示例运行(Python 2.7.6)

List 5.26431703568
Tuple 5.28769207001
String 3.16058015823

List 5.30263400078
Tuple 5.17412590981
String 3.17718791962

List 5.21962976456
Tuple 5.35261583328
String 3.22652792931

2 个答案:

答案 0 :(得分:3)

tl; dr:字符串index来电有很多优化,并且不必进行丰富的比较"。 listtuple s 都必须这样做;可变性并不重要。


如果您打开stringobject.c,则可以看到index来电string_find_internal,呼叫stringlib_find_slice,呼叫stringlib_find,呼叫{{1} }}

fastsearch在评论中指向this page,如果您有兴趣,请查看它。关于如何在python中实现Boyer-Moore子字符串搜索,它有一些有趣的内容。但这在你的1字符子字符串搜索中并不重要,fastsearch显式特殊情况:

fastsearch

非常紧的循环,紧密的循环在C中非常快。

好的,这涵盖了字符串。那么 } else if (mode == FAST_SEARCH) { for (i = 0; i < n; i++) if (s[i] == p[0]) return i; } tuple s呢?

这次要简单得多;这是两种类型必须执行的循环:

list

这个循环不必仅仅检查与for (i = start; i < stop && i < Py_SIZE(self); i++) { int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ); if (cmp > 0) return PyInt_FromSsize_t(i); 的相等性,而是必须在循环中每次迭代都进行PyObject_RichCompareBool。我没有太多具体细节进入代码(如果你很好奇的话,请查看object.c),但实际上这必须进行一些类型检查,然后查看这些类型是否实现了丰富的比较,然后调用该比较函数,检查它是否返回==单例,最后返回比较。

因此,该循环是NotImplemented调用中完成的大部分工作,并且列表和元组都必须这样做。字符串可以作弊。

答案 1 :(得分:1)

index将每个元素与给定对象进行比较。由于元组存储像列出python对象,因此比较需要相同的时间。字符串更快,因为比较字符比比较对象更快。