字符串对象PyStringObject

Python字符串对象PyStringObject

Python的字符串对象是一个不可变对象,任何改变字符串字面值的操作都是重新创建一个新的字符串。

astr = 'astr'
id(astr)
Out[22]: 59244376L
astr += 'another'
id(astr)
Out[24]: 59947360L

字符串对象在Python中用PyStringObject表示,扩展定义后如下。

typedef struct {
  Py_ssize_t ob_refcnt;            // 引用计数
  struct _typeobject *ob_type;     // 类型指针
  Py_ssize_t ob_size;             // 字符串的长度,不计算C语言中的结尾NULL
  long ob_shash;                   // 字符串的hash值,没有计算则为-1
  int ob_sstate;                   // 字符串对象的状态: 是否interned等
  char ob_sval[1];                 // 保存字符串的内存,默认先分配1个字符,用来保存额外的末尾NULL值
 
  /* 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;

ob_type字符串的类型指针,实际指向PyString_Type

ob_size保存的是字符串的实际长度,也是通过len(s)返回的长度值。而字符串实际占用的内存是ob_size + 1,因为C语言中需要额外的NULL作为字符串结束标识符。

ob_sval是实际存储字符串的内存,分配时会请求sizeof(PyStringObject)+size的内存,这样以ob_sval开始的内存长度就是size + 1的长度,正好用来存放以NULL结尾的字符串。

ob_shash是字符串的hash值,当字符串用来比较或者作为key时可以加速查找速度,默认值为-1。

ob_sstate记录字符串对象的状态。字符串可能有三种状态:

字符串的interned

字符串对象是不可变对象,因此相同的字面值的变量可以绑定到相同的字符串对象上,这样减少了字符串对象的创建次数。这样的行为称为interned。默认情况下空字符串和单字符字符串会被interned

另外一些情况下,例如__dict__、模块名字等预计会被大量重复使用或者永久使用的字符串,在创建时也会调用PyString_InternInPlace进行interned操作。

字符串对象的回收

当字符串的引用计数为零时会被回收。

字符串对象的其他操作

可以通过字符串对象的类的结构中找到对象的操作函数。

tp_base被赋值为PyBaseString_Type,因此字符串对象是basestring的子类。

最后更新于

这有帮助吗?