python底层设计:String对象设计

本文深入探讨Python的PyStringObject结构,包括PyString_Type、创建过程、Intern机制、字符缓冲池以及PyStringObject的效率问题。PyStringObject是Python字符串的内部表示,通过Intern机制实现字符串共享,减少内存浪费,而字符缓冲池则用于缓存单字符字符串。此外,文章还分析了字符串拼接的效率差异,指出使用join操作优于+操作。
摘要由CSDN通过智能技术生成

目录

 

1.PyStringObject与PyString_Type

2.PyStringObject的创建

3.Intern机制

4.字符缓冲池

5.PyStringObject 效率问题


1.PyStringObject与PyString_Type

  在python中,PyStringObject是对字符串对象的实现,PyStringObject是一个拥有可变长度内存的对象,这一点容易理解,因为“Hi”和“Lian”创建的PyStringObject其内部需要的内存空间不一样大小。同时,PyStringObject也是一个不可变对象,当创建一个PyStringObject对象后,其内部维护的字符串不能再发生改变。

PyStringObject的定义:

typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];

} PyStringObject;

      在PyStringObject定义我们可以看到,它的头部实际是一个PyObject_VAR_HEAD,其中有一个ob_size变量保存着对象中维护的可变长度内存的大小ob_sval是一个字符数组,但是它是作为一个字符指针指向一段内存的,这段内存保存着这个字符串对象维护的实际字符串。

     同c中的字符串一样,PyStringObject内部维护的字符串在末尾以‘\0’结尾,所以ob_sval指向的是一段长度为ob_size+1个字节的内存,且ob_sval[ob_szie] ='\0'.

    ob_shash的作用是缓存对象的hash值,这样可以避免每一次都要重新计算该字符串对象的hash值,如果PyStringObject还没被计算过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 = a->ob_size;
	p = (unsigned char *) a->ob_sval;
	x = *p << 7;
	while (--len >= 0)
		x = (1000003*x) ^ *p++;
	x ^= a->ob_size;
	if (x == -1)
		x = -2;
	a->ob_shash = x;
	return x;
}

    ob_sstate变量标记该对象是否已经过intern机制处理,intern机制是这节非常重要的点。

PyStringObject的类型对象是PyString_Type

PyTypeObject PyString_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
	0,
	"str",
	sizeof(PyStringObject),
	sizeof(char),
	string_repr, 				/* tp_repr */
	&string_as_number,			/* tp_as_number */
	&string_as_sequence,			/* tp_as_sequence */
	&string_as_mapping,			/* tp_as_mapping */
	(hashfunc)string_hash, 			/* tp_hash */

	string_methods,				/* tp_methods */

	&PyBaseString_Type,			/* tp_base */
    .......
	string_new,				/* tp_new */
	PyObject_Del,	                	/* tp_free */
};

     我们可以看到,tp_itemsize被设置为sizeof(char),对于python中任意变长对象,tp_itemsize这个域必须设置,它指明了由变长对象保存的元素的单位长度,tp_itemsize和ob_size共同决定了还需要额外申请的内存大小。

2.PyStringObject的创建

       python提供了两条路径从c中原生的字符串创建PyStringObject对象:

PyAPI_FUNC(PyObject *) PyString_FromStringAndSize(const char *, Py_ssize_t);
PyAPI_FUNC(PyObject *) PyString_FromString(const char *);

      我们先查看PyString_FromString的源码:

PyObject *PyString_FromString(const char *str)
{
	register size_t size;
	register PyStringObject *op;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值