python内存管理机制

python事先分配好的缓冲区

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

  1. 使用进行扩展
    这里写图片描述
    能够发现,用
    进行扩展出来的元素地址都是相同的,能够大体猜出 * 的行为,就是进行浅拷贝,将引用复制成三分,可是这也会形成问题,当给其中一个赋值的时候,其余使用 * 扩展出来的元素也会相应的跟着发生变换。使用生成器能够避免该问题。
    这种状况只会在列表嵌套的状况下发生,若是列表没有嵌套的话,赋值的时候会从新给被赋值的元素开辟一片新的空间
    这里写图片描述
    从图中能够看出,当X[0]赋值以后,其id发生了变化。
  2. 单独声明
    这里写图片描述 从上图能够看出,三个列表都单独声明的话,会给三个列表不同的地址,这样就避免了给其中一个赋值,另外一个相对应跟着改变的问题。