python解释器会事先分配一些缓冲区,这些缓冲区保存一些固定值,例如[-5,256],在一次程序执行过程当中,这些值的地址是固定的,是静态缓冲区。
可是每次从新运行程序,解释器会从新分配内存,因此每次运行程序的地址会不一样。
能够看出全部的引用都指向一片内存
再给出一个例子:
这里的1,0地址是不变的,变的是X,Y的引用对象,以下图:
string类型,它也有本身的缓冲区,固定的是256个ASCII码字符。
###python重复利用的缓冲区
在python中,除了事先分配好的缓冲区,还会有一些重复利用的动态缓冲区,配合垃圾回收机制,自动将没用的对象清除出缓冲区,以便新的变量能够有内存可用。
从上图能够看出在X大于256以后,保存数字的缓冲区地址在动态变换,可是也有例外的状况:
对于这种状况,应该是编译器对语句进行了优化,由于X=258,而后又判断X是否是258,因此编译器直接进行了跳步,将两句并一句,在编译阶段直接给出了答案。python
###容器类的内存分配
Python的容器类对象(表,词典,集合,等)保存的是各个元素的引用,而不是元素自己。
给出一个简单的例子:
根据上图能够看出X,Y的地址并非X[0],Y[0]的地址,而X[0],Y[0]的地址才是0和1所保存的地址。
对X,Y进行简单的交换,能够获得:
对比上一张图,能够发现Y其实就是X的引用,而X寻找了一片新的内存空间,并无用Y的地址。其关系以下:
在python中,容器类型即便彻底同样也可能存储在不一样的地址当中,如图所示:
在图中,打印了5次id,打印出来三个不一样的id值。
而且用is判断引用是否相同,给出了False的结果。
再看下边的例子:
这个例子中经过getrefcount函数看到,X,Y,Z各被引用了两次,也就意味着X,Y,Z对应着不一样的地址。尽管X,Y,Z的值都是[0,1],可是每个都有不一样的地址,互不干扰。而单独调用sys.getrefcount([0, 1])
发现仅有一次调用记录,也就是getrefcount函数调用的。这说明单独调用[0, 1]会再生成一片空间单独存放该对象,不会去引用X,Y或Z。
python的动态内存管理机制致使动态申请的内存可能刚申请下来,就被看成垃圾回收。给出一个例子:
如图所示,在打印出[0,1]的id以后,该列表就被回收了,进而将地址让给了[2,3]继续使用。web
容器类嵌套的地址分布会出现多种可能性svg