字符串驻留机制在许多面向对象编程语言中都支持,比如Java、python、Ruby、PHP等,它是一种数据缓存机制,对不可变数据类型使用同一个内存地址,有效的节省了空间,本文主要介绍Python的内存驻留机制。驻留 字符串驻留就是每个字符串只有一个副本,多个对象共享该副本,驻留只针对不可变数据类型,比如字符串,布尔值,数字等。在这些固定数据类型处理中,使用驻留可以有效节省时间和空间,当然在驻留池中创建或者插入新的内容会消耗一定的时间。 下面举例介绍python中的驻留机制。python内存驻留 在Python对象及内存管理机制一文中介绍了python的参数传递以及以及内存管理机制,来看下面一段代码:l1〔1,2,3,4〕l2〔1,2,3,4〕l3l2print(l1l2)print(l1isl2)print(l2l3)print(l2isl3) 知道结果是什么吗?下面是执行结果:TrueFalseTrueTrue l1和l2内容相同,却指向了不同的内存地址,l2和l3之间使用等号赋值,所以指向了同一个对象。因为列表是可变对象,每创建一个列表,都会重新分配内存,列表对象是没有内存驻留机制的。下面来看不可变数据类型的驻留机制。整型驻留 在Jupyter或者控制台交互环境中执行下面代码:a1300b1300c1b1print(a1isb1)print(c1isb1)a2200b2200c2b2print(a2isb2)print(c2isb2) 执行结果:FalseTrueTrueTrue 可以发现a1和b1指向了不同的地址,a2和b2指向了相同的地址,这是为什么呢? 因为启动时,Python将一个5256之间整数列表预加载(缓存)到内存中,我们在这个范围内创建一个整数对象时,python会自动引用缓存的对象,不会创建新的整数对象。 浮点型不支持:a1。0b1。0print(aisb)print(ab)结果FalseTrue 如果上面的代码在非交互环境,也就是将代码作为python脚本运行的结果是什么呢?(运行环境为python3。7)TrueTrueTrueTrueTrueTrue 全为True,没有明确的限定临界值,都进行了驻留操作。这是因为使用不同的环境时,代码的优化方式不同。字符串驻留 在Jupyter或者控制台交互环境中:满足标识符命名规范的字符串都会被驻留,长度不限。空字符串会驻留使用乘法得到的字符串且满足标识符命名规范的字符串:长度小于等于20会驻留(peephole优化),Python3。7改为4096(AST优化器)。长度为1的特殊字符(ASCII字符中的)会驻留空元组或者只有一个元素且元素范围为5256的元组会驻留 满足标识符命名规范的字符:aHelloWorldbHelloWorldprint(aisb)aHelloWorldbHelloWorldprint(aisb) 结果:FalseTrue 乘法获取字符串(运行环境为python3。7)aaa50baa50print(aisb)aaa5000baa5000print(aisb) 结果:TrueFalse 在非交互环境中:默认字符串都会驻留使用乘法运算得到的字符串与在控制台相同元组类型(元组内数据为不可变数据类型)会驻留函数、类、变量、参数等的名称以及关键字都会驻留 注意:字符串是在编译时进行驻留,也就是说,如果字符串的值不能在编译时进行计算,将不会驻留。比如下面的例子:letterdaHelloWorldbHelloWorldcHelloWorlddHelloWorllettere。join(〔Hello,World〕)print(id(a))print(id(b))print(id(c))print(id(d))print(id(e)) 在交互环境执行结果如下:16969033091681696903310128169690326929616969020741601696903282800 都指向不同的内存。 python3。7非交互环境执行结果:14263944397281426394439728142639443972814263945715041426394571440 发现d和e指向不同的内存,因为d和e不是在编译时计算的,而是在运行时计算的。前面的aaa50是在编译时计算的。强行驻留 除了上面介绍的python默认的驻留外,可以使用sys模块中的intern()函数来指定驻留内容importsysletterddasys。intern(HelloWorld)bsys。intern(HelloWorld)csys。intern(HelloWorld)dsys。intern(HelloWorlletter)esys。intern(。join(〔Hello,World〕))print(id(a))print(id(b))print(id(c))print(id(d))print(id(e)) 结果:19405935683041940593568304194059356830419405935683041940593568304 使用intern()后,都指向了相同的地址。总结 本文主要介绍了python的内存驻留,内存驻留是python优化的一种策略,注意不同运行环境下优化策略不一样,不同的python版本也不相同。注意字符串是在编译时进行驻留。 THEEND