本文主要阐述三个问题:

  1.PyStringObject(字符串对象)

  2.PyString_Type(字符串对象的类型)

  3.创建字符串对象

一、PyStringObject(字符串对象)

[stringobject.h]
typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;  
    char ob_sval[1];  
/* Invariants: * ob_sval contains space for 'ob_size+1' elements. * ob_sval[ob_size] == 0. * ob_shash is the hash of the string or -1 if not computed yet. * ob_sstate != 0 iff the string object is in stringobject.c's * 'interned' dictionary; in this case the two references * from 'interned' to this object are *not counted* in ob_refcnt. */ } PyStringObject;
1 #define PyObject_VAR_HEAD               \
2             PyObject_HEAD                       \
3             Py_ssize_t ob_size;

  PyStringObject是一个拥有可变长度内存的对象。比如:“hi”和"python"是两个不同的PyStringObject对象,其内部所需的保存字符串内容的内存空间显然是不一样的。

同时PyStringObject对象又是一个不变对象。为什么这样说呢?当创建一个PyStringObject对象之后,该对象内部维护的字符串就不能改变了。也就是在创建字符串对象时,其内存是不定的,在这个层面上,它是一个可变对象;但是一旦字符串创建后,其长度就不能改变了,在这个层面,它又是不变对象。

  PyObject_VAR_HEAD,其中有一个ob_size变量保存对象维护的可变长度内存的大小。

  [python源码剖析]字符串对象(一)

  char ob_sval[1];//作为一个字符指针指向一段内存,这段内存保存着字符串对象维护的实际字符串。

  内存的实际长度(字节),由ob_size维护,这是python所有变长对象的实现机制。比如PyStringObject对象“python”,ob_size值就是6。ob_sval指向一段长度为ob_size+1个字节的内存,因为在C语言中,字符串结尾的标志位'\0',而存在這样一种可能,字符串 中间就有'\0',因此,在pytho中,判断字符结束的条件是ob_sval[ob_size] == '\0'。

  ob_shash作用是缓存该对象的hash值,这样就避免了每一次重新计算该字符串对象的hash值。如果一个对象还没没有计算过hash值,那么初始ob_shash=-1。

  hash值采用以下算法: 

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);
                if (len == 0) {
                    a->ob_shash = 0;
                    return 0;
                }
                p = (unsigned char *) a->ob_sval;
                x = _Py_HashSecret.prefix;
                x ^= *p << 7;
                while (--len >= 0)
                    x = (1000003*x) ^ *p++;
                x ^= Py_SIZE(a);
                x ^= _Py_HashSecret.suffix;
                if (x == -1)
                    x = -2;
                a->ob_shash = x;
                return x;
            }
View Code

相关文章: