Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python 2.7中获取字符串的特定字符的性能_Python_Performance_Python 2.7 - Fatal编程技术网

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

在Python 2.7中获取字符串的特定字符的性能,python,performance,python-2.7,Python,Performance,Python 2.7,假设我想在Python2.7中获取字符串的特定字符,假设 a = 'abcdefg...' # a long string print a[5] 想知道何时访问字符串的任何特定字符,例如,访问第5个元素,想知道性能是什么,是恒定时间O(1),还是线性性能O(n)根据5(我们正在访问的字符的位置),还是整个字符串的线性性能O(n)(在本例中为len(a)) 问候,, 林 在我看来像O(1) 他们之所以这样做是因为字符串是连续的内存位置,所以索引到它只是一个偏移的问题。。。如果你知道c/c++是类

假设我想在Python2.7中获取字符串的特定字符,假设

a = 'abcdefg...' # a long string
print a[5]
想知道何时访问字符串的任何特定字符,例如,访问第5个元素,想知道性能是什么,是恒定时间O(1),还是线性性能O(n)根据5(我们正在访问的字符的位置),还是整个字符串的线性性能O(n)(在本例中为len(a))

问候,, 林

在我看来像O(1)


他们之所以这样做是因为字符串是连续的内存位置,所以索引到它只是一个偏移的问题。。。如果你知道c/c++是类似于
*(指针+偏移量)
(我已经很久没有做c了,所以这可能有点错误)

除了Joran的答案,我会告诉你,确认他的答案是O(1)查找

/*字符串片a[i:j]由字符a[i]。。。a[j-1]*/
静态PyObject*
字符串片(寄存器PyStringObject*a,寄存器Py\u ssize\u t i,
寄存器Py_ssize_t j)
/*j--可能是负数!*/
{    
if(i<0)
i=0;
if(j<0)
j=0;/*避免下一行出现有符号/无符号错误*/
如果(j>Py_尺寸(a))
j=Py_尺寸(a);
如果(i==0&&j==Py_大小(a)&&PyString_校验精确(a)){
/*它与a*/相同
Py_增量(a);
返回(PyObject*)a;
}    
if(job_sval+i,j-i);
}

为什么这应该是你的直觉

。这种常见的优化允许一些技巧,如在需要时假设连续数据。注意,在后台,我们有时只需要计算C中内存位置的偏移量(显然是特定于实现的)

其中字符串的不变性是可以依赖(或困扰)的。用python作者的话来说

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


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

谢谢Joran,投票赞成,我也有同样的感觉/结果,我很好奇它是如何在内部实现的,以获得O(1)性能的?如有任何详细或高层次的想法,我们将不胜感激。:)我认为这是因为。。。虽然他们没有特别标注字符串,但它离列表足够近了……很好的参考资料Joran。投赞成票,如果允许的话,我会在2分钟内将你的答复标记为答复。你回答得太快了。:)我同意-表中任何关于元组的内容都可能应用于字符串(虽然没有仔细查看,但可能)。python文档在很多地方进行了类比,实现也很相似。。。英雄所见略同。。。(请参阅我的编辑)从me@Joran哈哈,你的也加了1,那编辑是在我打字的时候出现的。我希望你不要加入我的链接,否则我将不得不取消post@IharBury感谢您对一个老问题的反馈:)为什么PyString_来自StringAndSize而不是O(1)?在相同的参考实现中,我没有看到任何“循环”;有一个MALOC调用,你认为是“不是O(1)”吗?我通常不考虑与字符串大小成正比的那些,这似乎与其他答案一致:@ IharBury HMM,在整个字符串上发生了什么?确实,它可能会复制字符串的片段,但OP要求访问单个字符,因此这将是一个元素上的memcpy(在我看来,引用有一个特定的情况,不是针对大小为1的对象的memcpy,而是对它们进行内部处理(第104行)请注意,对于OP的情况,j-1==1,我们并不是在整个初始对象上调用PyString_FromStringAndSize,因为它可能是字符串长度的线性性能。比如,访问一个大字符串的第一个字符需要花费很长时间,因为它必须预加载所有字符,或者它存储在一些乱码字典/链接列表中ing:)我想Python做了更奇怪的事情。。。
>>> 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