(Python学习3)字符串对象

typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;          // 记录该字符串对象的hash值,避免重复计算
    int ob_sstate;          // 对象状态,是否interned
    char ob_sval[1];        // 实际存储的是字符串值的指针
} PyStringObject;

字符串对象模型如下,与《python源码剖析》中稍许不同

(Python学习3)字符串对象_第1张图片

1、PyStringObject对象的创建

创建 PyStirngObjecet 时,先在对象池中查找,有则返回,无则创建并加入缓冲池。对象缓冲池为即为interned,实质为字典对象dict_object。

PyString_FromString(const char *str)      // 有删减
{
    register size_t size;
    register PyStringObject *op;
    size = strlen(str);

   if (size == 0 && (op = nullstring) != NULL) {
        return (PyObject *)op;
   if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
        return (PyObject *)op;

   op = (PyStringObject *)PyObject_MALLOC(PyStringObject_SIZE + size);   // 创建对象
   ……    
  
    /* 将长度较短PyStringObject对象加入对象池 */	
    if (size == 0)
        ……
    else if (size == 1)
        ……
    return (PyObject *) op;
}

size为0返回nullstring,size为1在字符缓冲池中查找并返回。

其实更长的字符串也共享了对象池,却没有找到代码。

2、Intern机制

PyString_InternInPlace(PyObject **p){                   // 有删减
    PyStringObject *s = (PyStringObject *)(*p);
	……
    if (interned == NULL)
        interned = PyDict_New();
    t = PyDict_GetItem(interned, (PyObject *)s);
    if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0)
        ……
}
由上函数可以看出,对象池interned实质为字典对象,并且key与value都是同一个PyStringObject对象的指针。并且在查找前需要创建临时PyStringObject对象作为key。

(Python学习3)字符串对象_第2张图片


3、字符缓冲池

static PyStringObject *characters[UCHAR_MAX + 1];
characters[]中存储了256个单字符的PyStringObject对象的指针。

characters[*str & UCHAR_MAX]   // 此语句即可直接定位到 str 对象的指针


你可能感兴趣的:((Python学习3)字符串对象)