PyStringObject需要保存字符串长度(ob_size),当产生字符串对象后,将不会改变(不可变对象)。这一特性使得PyStringObject对象可作为dict的键值,同时也使一些字符串操作的效率大大降低了,比如字符串连接操作。
typedef struct {
PyObject_VAR_HEAD
long ob_shash;
int ob_sstate;
char ob_sval[1];
} PyStringObject;
同c语言一样,字符串末尾以‘\0’结尾,但是中间可以出现’\0’,ob_sval指向一段长度为ob_size+1个字节的内存,字符串结束需要满足ob_sval[ob_size] == ‘\0’
Ob_hash缓存该对象的hash值,初始值为-1。Ob_sstate在书后面介绍intern机制,对于被intern之后的字符串,在整个python运行期间,系统中都只有唯一一个与该字符串对应的PyStringObject对象。当判断两个PyStringObject对象是否相同时,如果都被intern了,只要检查对应的对象是否相同即可。
PyStringObject对应的类型对象为PyString_Type,tp_itemsize被设置成sizeof(char),即一个字节。与ob_size共同决定申请多少内存。
字符串对象有长度限制,大小为2GB。
Intern机制对相同字符串的处理:
a = “python”
b=”python”
print a,b
intern机制的关键,是有一个叫interned的字典,记录intern机制处理过的PyStringObject对象。
对于上面的例子,先创建PyStringObject对象a,先会检查interned字典里有没有字符串与a相同,这里显然没有,将会添加到interned字典里。当创建b后(必须先要创建)执行intern操作,继续检查interned字典,发现有相同的字符串对象a,然后指向b的PyObject指针将指向a,b的引用计数减1,b将会被回收了。
有长度为256的字符缓冲池,添加到缓冲池的流程:当在创建PyStringObject对象时(还没创建),先检查长度。为字符时,再检查字符缓冲池是否有该字符,有,直接返回缓冲的该对象,结束;没有,创建PyStringObject对象,检查长度为字符,对对象进行intern操作,最后缓存至字符缓冲区。创建StringObject的两个函数不是太长也有注释,还能看懂。
字符串连接
通过”+”操作符对字符串进行连接是,调用string_concat函数:先计算连接后的字符串的长度,然后创建新的字符串对象分配给他计算的长度内存,最后复制。
Join操作,调用函数string_join:基本流程和“+”操作符相同。这里的区别是,“+”操作符有两个字符串就要创建一个新对象,join是对列表中的所有字符串进行,只要创建一次新对象就行。当进行多个字符串的连接时,应使用join操作。
上一篇: python源码剖析笔记-对象多态和对象池
下一篇: 用golang写的小的基于udp协议的聊天室程序
0 Responses so far.