Python字符串比较性能不一致

时间:2015-07-21 17:46:39

标签: python string time char compare

我想检查字符串比较是如何工作的(我想查看它是否是char的char,如果它在比较之前检查字符串的长度),所以我使用了这段代码:

s1 = 'abc'
s2 = 'abcd'
s3 = 'dbc'
s4 = 'abd'
t1 = time.clock()
s1==s2
print time.clock() - t1
t2 = time.clock()
s1==s3
print time.clock() - t2
t3 = time.clock()
s1==s4
print time.clock() - t3

当我在非常长的字符串(~30MB文本文件)上尝试相同的事情时,它工作得很好,我发现它确实执行了长度检查,并且它还将char与char进行比较。 但是当我在短字符串上尝试它时(例如上面代码中的字符串),性能结果非常不一致。 任何人都知道为什么他们不一致或我做错了什么? (也许我错了,比较不像我想的那样有效?)

编辑:我也尝试过的一个例子是将不同长度的字符串与特定字符串进行比较。我认为花费最长的那个将是具有另一个的确切长度的字符串,因为其余的将落入长度检查中,但它也不一致)。 让我说我正在检查的字符串是'你好',所以我比较'a','aa','aaa'等等... 我期待看到最长的支票将是'aaaaa',但它是'a',我不知道为什么。

2 个答案:

答案 0 :(得分:2)

在非常短的时间内,您可能会得到不一致的结果。 通过多次重复操作可以获得更好的结果,从而使差异很大:

t1 = time.clock()
for i in range(10**6):
    s1 == s2
t2 = time.clock()

更好的是,使用timeit模块来处理重复(以及其他细节) 喜欢关闭垃圾收集):

import timeit

s1 = 'abc'
s2 = 'abcd'
s3 = 'dbc'
s4 = 'abd'
t1 = timeit.timeit('s1==s2', 'from __main__ import s1, s2', number=10**8)
t2 = timeit.timeit('s1==s3', 'from __main__ import s1, s3', number=10**8)
t3 = timeit.timeit('s1==s4', 'from __main__ import s1, s4', number=10**8)
for t in (t1, t2, t3):
    print(t)

产量

2.82305312157
2.83096408844
3.15551590919

因此s1==s2s1==s3花费的时间基本相同。 s1==s4需要更多时间,因为在相等可以返回False之前必须比较更多字符。

顺便说一下,time.clock使用timeit.default_timer进行衡量 在Windows上的时间,time.time使用timeit.default_timer进行衡量 在Unix上的时间。使用timeit.default_timer代替time.clocktime.time 使您的代码更具跨平台兼容性。

答案 1 :(得分:1)

在比较内容之前,字符串比较长度是正确的(至少在2.7中)。 Herestring_richcompare的相关部分:

if (op == Py_EQ) {
    /* Supporting Py_NE here as well does not save
       much time, since Py_NE is rarely used.  */
    if (Py_SIZE(a) == Py_SIZE(b)
        && (a->ob_sval[0] == b->ob_sval[0]
        && memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0)) {
        result = Py_True;
    } else {
        result = Py_False;
    }
    goto out;
}

简单来说,检查似乎是:

  • 如果字符串具有相同的内存地址,则它们是相等的。 (上图中没有图片)
  • 如果字符串的大小不同,则它们不相等。
  • 如果字符串具有不同的第一个字符,则它们不相等。
  • 如果字符串具有相同的字符数组,则它们是相等的。

第三项检查似乎并非绝对必要,但如果手动检查数组内容比调用memcmp更快,则可能是优化。

如果您的基准测试向您建议比较不同长度的字符串比比较相同长度的字符串慢,这可能是clock不完全可靠行为导致的误报,如其他答案所述和评论。