performance of get a specific character of a string in Python 2.7
假设我想在python 2.7中得到一个字符串的特定字符,假设
1 2 | a = 'abcdefg...' # a long string print a[5] |
想知道何时访问字符串的任何特定字符,例如,访问第5个元素,想知道性能是什么,是根据5(我们正在访问的字符的位置)的常量时间o(1)还是线性性能o(n)还是整个字符串的线性性能o(n)(在本例中是len(a))?
当做,林
除了Joran的答案之外,我还将向您指出这个引用实现,确认他的答案是O(1)查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* 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作者的话来说;
There are several advantages [to strings being immutable]. One is
performance: knowing that a string is immutable means we can allocate
space for it at creation time
因此,尽管我们可能无法保证,就我所知,跨实现的这种行为,但是假设它是非常安全的。
1 2 3 4 5 6 7 8 9 10 | >>> 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++类似EDCOX1的0个词(自从我做了C,所以可能有点错误),就没有寻求(至少这是我的理解)。