Python字符串的intern机制和大小整数对象池

不多BB,直接上实例

字符串的Intern机制

(1)
>>> a = 'hello'
>>> b = 'hello'
>>> print(id(a),id(b))
2037326236784 2037326236784

>>> a = 'hello world'
>>> b = 'hello world'
>>> print(id(a),id(b))
2037326180976 2037326180784

(2)
>>> a = 'hello'*4
>>> b = 'hello'*4
>>> print(id(a), id(b))
2037326166320 2037326166320

>>> a = 'hello'*5
>>> b = 'hello'*5
>>> print(id(a), id(b))
2037326142960 2037326143040

(3)
>>> a = ' '    # 字符串中有一个空格
>>> b = ' '    # 字符串中有一个空格
>>> print(id(a), id(b))
2037324558664 2037324558664

有朋友可能碰到这些情况时纳闷,怎么肥四?其实这是Python字符串的intern机制的锅,该机制规定:当两个或以上的字符串变量它们的值相同且仅由数字字母下划线构成而且长度在20个字符以内,或者值仅含有一个字符时,内存空间中只创建一个对象来让这些变量都指向该内存地址。当字符串不满足该条件时,相同值的字符串变量在创建时都会申请一个新的内存地址来保存值。

小整数对象池

Python字符串有intern机制的限制,同样的,整形数也有大小整数对象池的限制。Python语言在设计之初为了减少频繁申请和销毁内存的资源开销,规定了[-5, 256]之间的整数全部常驻在内存中且不会被垃圾回收只能增减引用计数,这就是小整数对象池,池外的数在创建时每次都得申请新的内存空间而不是增加引用计数。例子如下:

>>> a = 256
>>> b = 256
>>> print(id(a), id(b))
1953505712 1953505712
>>> a = 257
>>> b = 257
>>> print(id(a), id(b))
2037325924592 2037325924368

大整数对象池

在交互式终端环境中,每次创建大型数时都是去申请新的内存空间。但是在编写Python文件时每次运行都把代码加载到内存中,整个项目代码都属于一个整体。这时就是大型整数对象池发挥作用的时候了,它把处于相同代码块的所有等值的大型整数变量都处理为一个对象。不懂就看实例。

class A(object):
    a = 100
    b = 100
    c = 1000
    d = 1000


class B(object):
    a = 100
    b = 1000


print(A.a is A.b)  # True
print(A.a is B.a)  # True
print(A.c is A.d)  # True  重点是这一个
print(A.b is B.b)  # False

瞅见了吧,类A和类B在同一文件中,虽然1000超出了[-5, 256]的范围但是还是把他们处理成同一个对象了。

题外扩展

扩展点Python内存管理方面的姿势吧,我也是刚看到的,顺便贴这儿了,希望对你们有用。

>>> id([1,2,3]) == id([4,5,6])
True
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> print(id(a), id(b))
2037326252488 2037326229256

有人问为什么id([1,2,3]) == id([4,5,6]),这是因为Python会实时销毁没有引用计数的对象。一旦在内存中创建了一个对象但是没有为其添加引用计数,该段代码执行完后就会回收地址,在这个例子中计算完[1,2,3]的id后list被销毁,计算右边的id时list实时创建,复用了左边list用过的内存。但是生成的时间有先后,他们并不代表同一个对象。

猜你喜欢

转载自my.oschina.net/u/3723649/blog/1815000