还是带着问题上路吧,和整数对象的实现同样的问题:
>>> a=‘abc‘ >>> b=‘abc‘ >>> a is b True >>> c=‘abc‘*10 >>> d=‘abc‘*10 >>> d is c False
why?在整数对象的实现中,对待小整数有小整数对象池,对待大整数对申请内存,字符串对象的实验也是这样的吗???
NO
先看下字符串对象的定义:
typedef struct{ PyObject_VAR_HEAD long ob_shash; int ob_sstate; char ob_sval[1]; }PyStringObject;
其中:
PyObject_VAR_HEAD中的ob_size存放字符串实际长度
ob_shash用来缓存该字符串对象的实际hash值
ob_sstate标记该对象是否经过intern机制处理
ob_sval指向一段长度为ob_size+1字节的内存,ob_sval[ob_size+1]必须为‘\0‘
字符对象的创建就是计算字符串的长度,申请一段内存,把字符串用memcpy复制进去,然后创建这个对象,看好,所有的字符串都会创建对象。(代码就不贴了。。。)
重要的是intern机制,这个机制是什么东西?
说白了,intern机制就是每创建一个比较短的字符串对象,就在一个叫interned的字典里面查看是否存在字符串相同的字符串对象,如果存在的话,就把字典存放的对象的ob_refcnt加1,然后销毁新创建的对象,所以才会出现上面的情景 a is b?True
字符串对象除了intern机制以外,还有类似于小整数对象的字符缓冲池,其实就是用一个类似于数组的东西(characters array)指向这个对象,对只有一个字符的字符串,第一次创建时候会进行如下操作:
1.创建对象
2.对其进行intern操作
3.将对象放进字符缓冲池
那么下次再创建这个字符对象时候,会首先查看字符缓冲池中是否存在这个对象,如果存在的话,返回这个缓冲对象。区别于小整数对象的是,小整数对象在python解释器初始化之初就创建了,而字符串缓冲池指向的对象直到用到的时候才会创建。
参考资料:
python源码剖析
Python string objects implementation