繁体   English   中英

在 Python 2.7 中获取字符串的特定字符的性能

[英]Performance of get a specific character of a string in Python 2.7

假设我想在 Python 2.7 中获取字符串的特定字符,假设

a = 'abcdefg...' # a long string
print a[5]

想知道何时访问字符串的任何特定字符,例如访问第 5 个元素,想知道性能是什么,是常数时间 O(1),还是线性性能 O(n),要么根据 5(字符的位置我们正在访问),还是对整个字符串的线性性能 O(n)(在本例中为 len(a))?

>>> long_string_1M ="".join(random.choice(string.printable) for _ in xrange(1000000))
>>> short_string = "hello"
>>> timeit.timeit(lambda:long_string_1M[50000])
0.1487280547441503
>>> timeit.timeit(lambda:short_string[4])
0.1368805315209798
>>> timeit.timeit(lambda:short_string[random.randint(0,4)])
1.7327393072888242
>>> timeit.timeit(lambda:long_string_1M[random.randint(50000,100000)])
1.779330312345877

对我来说看起来像 O(1)

他们实现了它,因为一个字符串是连续的内存位置,所以索引它只是一个偏移的问题......如果你知道 c/c++ 它就像*(pointer+offset) (自从我完成 C 以来已经很长时间了,所以这可能有点错误)

除了 Joran 的回答之外,我还会向您指出这个参考实现,确认他的回答是 O(1) 查找

/* String slice a[i:j] consists of characters a[i] ... a[j-1] */        
static PyObject *    
string_slice(register PyStringObject *a, register Py_ssize_t i,    
             register Py_ssize_t j)    
     /* j -- may be negative! */    
{    
    if (i < 0)    
        i = 0;    
    if (j < 0)    
        j = 0; /* Avoid signed/unsigned bug in next line */    
    if (j > Py_SIZE(a))    
        j = Py_SIZE(a);    
    if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) {    
        /* It's the same as a */    
        Py_INCREF(a);    
        return (PyObject *)a;    
    }    
    if (j < i)  
        j = i;    
    return PyString_FromStringAndSize(a->ob_sval + i, j-i);    
}

为什么这应该是你的直觉

Python 字符串是不可变的 这种常见的优化允许在需要时假设连续数据之类的技巧。 请注意,在幕后,我们有时只需要计算 C 中内存位置的偏移量(显然是特定于实现的)

有几个地方可以依赖(或烦恼)字符串的不变性。 用python作者的话来说;

[字符串不可变]有几个优点。 一是性能:知道字符串是不可变的意味着我们可以在创建时为其分配空间

因此,据我所知,尽管我们可能无法保证跨实现的这种行为,但可以假设是非常安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM