《Python源码剖析》阅读笔记:第三章-字符串对象

第三章-字符串对象

 字符串对象定义:
typedef struct {
PyObject_VAR_HEAD
long ob_shash;
int ob_sstate;
char ob_sval[1];
} PyStringObject;
由于字符串是变长对象,所以有变长对象头。
ob_shash用来缓存当前字符串的哈希值,这在以字符串作为key的dict对象查询时非常有用。
ob_sstate用来标记该字符串是否为interned。
最后这个ob_sval比较巧妙,定义的是一个字符的数组,他的作用其实是作为实际分配内存后,字符串缓冲区的指针。在实际给字符串对象分配内存时,Python申请的内存大小为PyStringObject + 字符串长度。Python规定字符串缓冲区末尾必须是'\0',所以由ob_sval实际指向的缓冲区的长度刚好是length + 1,而ob_sval正好又是字符串对象尾部缓冲区的指针。

字符串对象的intern机制:
对于相同的两个字符串,Python不会为其创建两个字符串对象,以节省内存。intern机制由一个全局的intern字典维护。当新建一个字符串时,运行时会在intern字典中查询是否已经存在这个字符串,如果存在,则直接增加字典里的字符串对象的引用计数;如果不存在,则将其添加到字典中。

和整数对象一样,字符串对象同样有对象池机制提供对ASCII码对象的快速引用。其原理是,当字符串被创建时,PyString_FromString函数会检查字符串长度,如果长度为1,则先创建字符串,然后intern字符串,最后将字符串对象指针保存在characters对象池中。以后访问字符串,如果长度为1,就直接从对象池中返回对象指针。

关于字符串拼接的效率:字符串拼接有两种方式,“+”操作符和str.join(iterable)函数。“+”操作符会调用string_concat函数。它会重新申请一块内存,然后将两个字符串复制到新的内存中,返回一个字符串对象。也就是说,N个字符串拼接会调用N-1次string_concat函数,即申请N-1次内存,效率是非常底下的。所以官方推荐str.join(iterable)函数,它接受一个list或tuple等可迭代对象,统计有多少个字符串,统一分配一次内存,然后复制左右字符串到新内存中,并返回字符串对象。可见后者效率要高很多


你可能感兴趣的:(python,list,String,struct)