【发布时间】:2017-05-01 13:51:33
【问题描述】:
短篇小说:
Python 3 unicode 字符串查找是 O(1) 还是 O(n)?
长篇大论:
在 C 字符数组中查找字符的索引是常数时间 O(1),因为我们可以确定地跳转到一个连续的内存位置:
const char* mystring = "abcdef";
char its_d = mystring[3];
和说的一样:
char its_d = *(mystring + 3);
因为我们知道sizeof(char) 在 C99 中是 1,并且由于 ASCII 的原因,一个字符适合一个字节。
现在,在 Python 3 中,字符串文字是 unicode 字符串,我们有以下内容:
>>> mystring = 'ab€cd'
>>> len(mystring)
5
>>> mybytes = mystring.encode('utf-8')
>>> len(mybytes)
7
>>> mybytes
b'ab\xe2\x82\xaccd'
>>> mystring[2]
'€'
>>> mybytes[2]
226
>> ord(mystring[2])
8364
采用 UTF-8 编码,字节 2 > 127,因此对字符 3 使用多字节表示。
由于字符的多字节表示,我只能得出结论,Python 字符串中的索引查找不能是 O(1)?这意味着mystring[2] 是 O(n),并且以某种方式正在执行内存数组的即时解释以查找索引处的字符?如果是这样的话,我是否错过了一些说明这一点的相关文档?
我做了一些非常基本的基准测试,但我无法推断出 O(n) 行为:https://gist.github.com/carlos-jenkins/e3084a07402ccc25dfd0038c9fe284b5
$ python3 lookups.py
Allocating memory...
Go!
String lookup: 0.513942 ms
Bytes lookup : 0.486462 ms
编辑:用更好的例子更新。
【问题讨论】:
-
177大于127,但小于255。 -
字符串的内部表示不必是 UTF-8。
-
>>> ord(mystring[3]) 233 >>> ord(mystring[2]) 241 >>> ord(mystring[4]) 98,均低于255 -
“在 ASCII 中,一个字符与一个字节相同”——这是不正确的。 C ** 指定
char正好是一个字节。 ASCII 是 7 位代码,因此 ASCII 字节将是 7 位,这在 C 中是不允许的。C 也没有要求特定的编码,只是最小字符集。