Python也被称为是一门非常透彻的语言,在当初设计者当初设计它的时候,大体的指导思想,就是对于一个特定的问题,只要有一种最好的方法来解决就OK了,下面对Python PyStringObject对象说明。
与定长对象不同,对于变长对象而言,对象维护的数据的长度在对象定义时是不知道的。对于PyIntObject来说,其维护的数据的长度在对象定义时就已经确定了。是一个long变量的长度;而可变对象维护的数据的长度只能在对象创建时才能确定,考虑一下,我们只能在创建一个字符串或一个列表时才知道它们所维护的数据的长度,在此之前,对这个信息,我们一无所知。
在变长对象中,实际上还可分为可变对象(mutable)和不可变对象(immutable),可变对象是在对象创建之后,其维护的数据的长度还能变化的对象。比如一个list被创建后,可以向其中添加元素或删除元素。
这些操作都会改变其维护的数据的长度;而不可变对象所维护的数据在对象创建之后就不能再改变了,比如Python中的string和tuple,它们都不支持添加或删除的操作。本章我们将研究Python变长对象中的不可变对象——字符串对象。
在Python中,PyStringObject是对字符串对象的抽象和表示。PyStringObject对象是一个拥有可变长度内存的对象,这一点非常容易理解,因为对于表示”Hi”和”Python”的两个不同的PyStringObject对象,其内部需要的保存字符串内容的内存空间显然是不一样的。
但同时,PyStringObject对象又是一个不变对象(Immutable)。当创建了一个PyStringObject对象之后,该对象内部维护的字符串就不能再被改变了。这一点特性使得PyStringObject对象能作为PyDictObject的键值,但同时也使得一些字符串操作的效率大大降低,比如多个字符串的连接操作。
PyStringObject对象的声明如下:
- [stringobject.h]
- typedef struct {
- PyObject_VAR_HEAD
- long ob_shash;
- int ob_sstate;
- char ob_sval[1];} PyStringObject;
在PyStringObject的定义中我们看到,在PyStringObject对象的头部实际上是一个PyObject_VAR_HEAD,其中有一个ob_size变量保存着对象中维护的可变长度内存的长度。虽然在PyStringObject的定义中,ob_sval是一个字符的字符数组。
但是ob_sval实际上是作为一个字符指针指向了一段内存,这段内存保存着这个字符串对象所维护的实际字符串,显然,这段内存不会只是一个字节。而这段内存的实际长度(字节),正是由ob_size来维护,这个机制是Python中所有拥有可变长度内存的对象的实现机制。比如对于PyStringObject对象”Python”,ob_size的值就是6。
同C中的字符串一样,PyStringObject内部维护的字符串在末尾必须以’\0’结尾,但是由于字符串的实际长度是由ob_size维护的,所以PyStringObject表示的字符串对象中间是可能出现字符’\0’的,这一点与C语言中不同,因为在C中。只要遇到了字符’\0’,就认为一个字符串结束了。所以,实际上,ob_sval指向的是一段长度为ob_size+1个字节的内存,而且必须满足ob_sval[ob_size] = ‘\0’。
【编辑推荐】