Python中的代码块缓存机制和非代码块缓存机制!
代码块的定义
Python程序是由代码块构造的。代码块是作为一个单元执行的一段Python程序文本。
也就是说一个类,一个函数,一个脚本文件都是一个代码块,此外,当你以交互式的方式输入的时候,一行就是一个代码块。
这是在ipython解释下以交互式方式输入,那么这个时候每一行就是一个代码块。
如果是在类似pycharm环境运行,那么整个脚本文件都是一个代码块。前提是没有函数或者类。
代码块的缓存机制
如果在同一个代码块内,会存在有一个缓存机制。
同一个代码块内,对对象进行初始化的时候,python解释器会在内存中寻找这个初始化的值是不是已经存在,如果存在则会引用自同一个内存空间。也就是说我们用is进行判断,应该返回的是True。也就是python解释器从上到下进行解释,遇到一个初始化的对象,就把这个对象,以一个类似字典的形式存在一个内存空间中。如果再遇到初始化语句,解释器就在这个内存空间寻找是否有同值的对象,如果有,则引用,如果没有,则重新开辟一个内存空间存放这个初始化的值。
这个机制适用的对象有:int,float,complex ,boolean,str,其中字符串要符合一定规则的,否则不会存在这个缓存机制。
下面来进行一些验证:
a = 100000000000000000000532758932759.419375091750151513515 b = 100000000000000000000532758932759.419375091750151513515 print(a is b) # True
c = '1478174%^%&$^&$&sfhoaihfoiaf' d = '1478174%^%&$^&$&sfhoaihfoiaf' print(c is d) # True
其实不管你整数或者小数有多长,都符合这个缓存机制,都是指向同一个内存地址。但是字符串就不一样了。
其实也算不上什么限制,看一下验证:
s_1 = '#'*4000 s_2 = '#'*4000 print(len(s_1)) print(s_1 is s_2) # True a_1 = '#'*4097 b_1 = '#'*4097 print(len(a_1)) print(a_1 is b_1) # False
在pycharm中测试大概字符串做乘法后长度不超过大约4097长度,那么还是符合这个机制的。
即便是中文也是符合这个的。
不管你是中文加符号加空格加数字加字母,只要长度不超过大约4097那么应该是符合这个机制的。都指向的是同一内存地址。
这样做的优点就是简化了内存空间,提升效率,避免重复的去开辟相同的值的内存空间
非同一代码块的缓存机制
非同一代码块的缓存机制其实和代码块的缓存机制很像,只不过对缓存的数据做了一些限制,将符合规定的数据存到了一个数据池当中,也就是一块内存空间中。
如果你初始化对象值在这个数据池中,那么直接引用就可以,不用再重新开辟一个内存空间存放这个值。这个数据池分为数字数据池和字符串数据池,数字数据池是事先已经创建好了的。
对于非同一代码块,符合机制的数据类型有 int,boolean,str
其中,整数只有(-5~256)
对于字符串,我看很多博客只写了只有全是数字,字母,下划线组成的字符串才符合这个机制,其实长度为1的字符串或者空字符串也是符合这个机制的。但是不能是中文。
下面进行一些验证,这里用的是jupyter,是ipython解释器的交互式命令工具,也就是说每一行就是一个代码块。
下面是字符串的验证:
当字符串做乘法的时候,和同一代码块的机制很像,但是只能是只有数字下划线和字母的字符串做乘法之后长度小于大约4097的长度才会驻留。
上面均采用jupyter为测试环境,每一行都是一个代码块。
如果是函数或者类和函数或类外部的非同一代码块。因为函数和类本身就是一个代码块。
强制驻留
也叫指定驻留,意思就是你可以制定一个字符串加入到字符串数据池中,后面的如果有对象初始化是这个值,则可以直接引用。
import sysa =sys.intern('&&^*^&*123') b = sys.intern('&&^*^&*123') print(a is b) # True
非同一个代码块,’&&*&*123’不符合字符串数据池的缓存机制,但是可以用sys模块的intern方法,强制驻留,强行加入到字符串数据池中。
此外Boolean在内存中就是0或者1就不再做额外讨论了。
更多Python知识,请移步云海天Python教程继续学习!!
来源:PY学习网:原文地址:https://www.py.cn/article.html