Python当中字符串的intern机制

首先我们来了解下什么是string interning(字符串驻留)

Incomputer science, string interning is a method of storing only onecopy of each distinct string value, which must be immutable. Interning strings makes some stringprocessing tasks more time- or space-efficient at the cost of requiring moretime when the string is created or interned. The distinct values are stored ina string intern pool. –引自维基百科

也就是说,值同样的字符串对象仅仅会保存一份,是共用的,这也决定了字符串必须是不可变对象。
其实我们想一想,就和数值类型一样,同样的数值仅仅要保存一份即可了,不是必须用不同对象来区分。

我们再来看看在Python当中的字符串intern机制

例如:

>>> a = 'opq'
>>> b = 'o' + 'pq'
>>> id(a)
66832910
>>> id(b)
66832910

能够看到它们实际上是同一个对象。

intern机制的优点是,在创建新的字符串对象时,会先在缓存池里面找是否有已经存在的值相同的对象(标识符,即只包含数字、字母、下划线的字符),如果有,则直接拿过来用(引用),避免频繁的创建和销毁内存,提升效率。
缺点是在拼接字符串时,或者在改动字符串时会极大的影响性能。原因是字符串在Python当中是不可变对象,所以对字符串的改动不是inplace(原地)操作,需要新开辟内存地址,新建对象。这也是为什么拼接字符串的时候不建议用‘+’而是用join()。join()是先计算出全部字符串的长度,然后再一一拷贝,仅仅创建一次对象。

>>> a = 'hello world'
>>> b = 'hello world'
>>> id(a)
66834385
>>> id(b)
66439216

这里由于字符串里面含有空格,导致不会触发intern机制。
可是为什么会这么做呢?既然Python的内置函数intern()能显式的对随意字符串进行intern,说明不是实现难度的问题。
答案在源代码StringObject.h中的注释能够找到:

/* … … This is generally restricted tostrings that “looklike” Python identifiers, although the intern() builtincan be used to force interning of any string … … */

也就是说intern机制仅仅对那些看起来像是Python标识符的字符串对象才会触发。

下面我们还得注意另外一个坑:

>>> 'op' + 'q' is 'opq'
>>> True  

>>> c = 'op'
>>> d = 'opq'
>>> c + 'q' is 'opq'
>>> False

为什么会出现这种情况?
不都只是包含字母吗,应该被主动intern的啊?
这是由于在第一个例子中,‘op’ + ‘q’是在compile-time(编译时)求值的,被替换成了’opq’,而在第二个例子中,c + ‘q’是在run-time(运行时)拼接的,导致没有被主动intern。

总结

  1. 单词,即Python标识符,不可修改,默认开启intern机制,共用对象,引用计数为0时自动被回收。
  2. 字符串(包含了除Python标识符以外的字符),不可修改,默认没有开启intern机制,引用计数为0时自动被回收。
  3. 特殊情况下(上述最后一个例子),不会被主动intern。
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值