python中字符串是一段连续的内存空间和字符串驻留机制

第二章开头作者提到序列可以根据是否能存放不同类型的item分为容器序列和扁平序列两种类型。这种区分方法本没有问题,因为一个序列总可以划分成为能存放不同类型的数据,和不能存放不同类型的数据。但关键是这么区分有什么意义。毕竟不可变序列和可变序列的划分对+=操作符和id的作用有所不同。
作者说其中扁平序列存放的是值而不是引用,它在内存中一段连续的内存空间。
但是经过测试,。

>>> a="xzz"
>>> id(a)
83971168
>>> id(a[0])
55290688
>>> id(a[1])
83970528
>>> id(a[2])
83970528

经过了解,这种现象由于python的字符串驻留机制引起的。
创建字符串的时候,内部确实是直接分配了连续空间,并将对象复制进去。

obj = (PyObject *) PyObject_MALLOC(struct_size + (size + 1) * char_size);

但是当我们对字符串切片时,会返回一个新的字符串对象,所以id某个单字符字符串事实上返回的是单字符在缓冲池中的位置。

    /* Single character Unicode objects in the Latin-1 range are
       shared when using this constructor */
    if (size == 1 && (Py_UCS4)*u < 256)
        return get_latin1_char((unsigned char)*u);
​
    /* If not empty and not single character, copy the Unicode data
       into the new object */
    if (find_maxchar_surrogates(u, u + size,
                                &maxchar, &num_surrogates) == -1)
        return NULL;

作者:松直
链接:https://juejin.im/post/5959bd395188250d7f23faf5
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结:切片取单字符事实上会返回一个新的单字符字符串对象,而由于字符串驻留机制,同一单字符字符串的id永远是相同的。

有趣的例外:

>>> a="我"
>>> b="wo "
>>> b="我"
>>> id(a)
83979392
>>> id(b)
83979440

这两个是不同的,这是由于字符串驻留只针对ASCII码做缓存。

官方文档对序列的定义是“以非负整数索引的有限且有序的集合”。序列(sequence)中的每一项被定义成item。
让我感兴趣的是str这个序列(和数字一样最长使用),根据文档,str不是内置类型。也没有单独的“字符”类型,对str切片得到是长度为1的字符串。

由于没有单独的“字符”类型,索引字符串会生成长度为1的字符串。也就是说,对于非空字符串s,s[0] == s[0:1]。

看来cpython处理字符串的时候,永远把它看成一个个长度为1的字符串的集合。
也许作者想说的是原子类型,但在python3文档中,完全没有提到原子类型。

可变和不可变类型的区别:

An object of an immutable sequence type cannot change once it is created. (If the object contains references to other objects, these other objects may be mutable and may be changed; however, the collection of objects directly referenced by an immutable object cannot change.)

item是由id,类型,值三个东西组成的东西。
简单说说,既然我们已经知道了序列是引用(id)的集合,只要序列本身各个item的引用不能被改变,它就是个不可变类型。
比如(1,2,[3,4])虽然元组中的列表内容会变,但列表的id不会变,所以元组是个不可变类型。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值