567
京东网上商城
[笔记]Python的字符串对象
PyStringObject定义在stringobject.h中,附有不少注释说明。1. PyStringObject实际上是一组字符,以'\0'结尾,且因为有只是长度的变量,所以也可以包含'\0'作为内容。
2. PyStringObject是不可变对象,所以a = "hello"和a = "world"先后执行后,a指向的是不同的对象了。
3. PyStringObject保存了hash值避免重复计算。
4. 采用intern机制来处理相同的字符串对象。
结构体定义如下:
typedef struct { PyObject_VAR_HEAD //不定长对象 long ob_shash; //如果还没计算,为-1 int ob_sstate; //如果该字符串在interned字典中,则该标志不为0。而且在这种情况下,两个来自interned字典的引用不算进ob_refcnt char ob_sval[1]; //用来作为指针指向保存字符串的内存区域,包含ob_size+1个元素 } PyStringObject;
计算哈希值的算法有必要MARK下,以后可以参考使用。
static long string_hash(PyStringObject *a) { register Py_ssize_t len; register unsigned char *p; register long x; if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); p = (unsigned char *) a->ob_sval; x = *p << 7; while (--len >= 0) x = (1000003*x) ^ *p++; x ^= Py_SIZE(a); if (x == -1) x = -2; a->ob_shash = x; return x; }
intern机制是用来确保相同的值的字符串对象只有一个存在,并且使得比较操作可以仅仅通过指针比较来完成。
它实际上是维护了一个字典(dict/map)interned,当字符串被interned时,会查找字典中键的存在,如果没有则放入。
这种方法可以在空间上节省,并不能节省时间,因为要判断是否存在于interned字典中,需要先创建字符串对象,才能去表中查找。
此外,这种方法默认针对Python的关键字、单字符、空串等。
当然,Python也提供了intern()内置函数来缓存用户想要的字符串对象。
缓存hash值以及intern机制为解释器加速了20%。
最后,是关于字符串的连接。
比如:str = str1 + str2 + str3 + str4,由于PyStringObject is immutable,所以会为3个+号执行3次内存的分配和复制
而如果将待连接的字符串放入可迭代对象中,使用string_join(PyStringObject的join操作),就会一次计算所需的总共内存大小,一次分配,然后再全部复制过去。
JasonLee 2011.08.08 0:33
最后更新:2017-04-02 22:16:35