python进阶之内存模型

 

 

每一个编程语言的背后都有自己独特的内存模型支持,比如最经典的C语言,一个int类型占8字节。那么在python中不区分数据类型,定义一个变量其在内存在占用多少字节呢?python中数据的运算其内存是如何变化的呢?

在回答上面的问题之前,首先看一下python中可变的数据和不可变数据


一、可变对象和不可变对象

Python一切数据皆为对象,python中的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容不可变。

不可变(immutable):数值(int、float)、字符串(string)、元组(tuple)

可变(mutable):字典型(dictionary)、列表型(list) 

 

 

 

根据对象的分类,可以将数据类型也做一个分类,可变数据类型与不可变数据类型:

可变数据类型:列表list和字典dict 

不可变数据类型:整型int、浮点型float、字符串型string和元组tuple 

  

这里的可变不可变,是指内存中的那块内容是否可以被改变。

如果是不可变类型,在对对象本身操作的时候,必须在内存中新申请一块区域(因为老区域不可变)。创建a=1整型对象,执行a=2时,内存中的对象1是不变的,只是重新创建了对象2。

如果是可变类型,对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请(+/-)即可,也就是它的内存地址会保持不变,但区域会变长或者变短。

 

当对可变和不可变对象运算时会内存中会发生什么事情呢?对比来看

不可变数据类型:不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象; 
可变数据类型:允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

 

python对于数据的特殊处理 

 

小整数

Python为了优化速度,避免为整数频繁申请和销毁内存空间,使用了小整数对象池。对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收。在这个范围内所有的整数都只会被建立一次。

 

a = 100
b = 100
print(id(a))
print(id(b))

-------------------------
94125443429088
94125443429088

  

a = 200
b = 200 

print a is b 
-----------------
True


a = 300
b = 300
print a is b
-----------------
False

 

大整数

大整数池: 只存储包含标准字符(数字、字母、下划线)的字符串,不包含特殊字符的字符串 。

python为了避免创建大整数浪费的内存空间和时间,将创建过的大整数加入大整数池。

python中大整数池,默认大整数池里面为空,每一个py程序都有一个大整数池。使用大整数时如果大整数池里不存在该整数的话,会新建一个大整数对象。下次使用大整数时直接使用大整数池里的对象,而不是创建新的对象 

py文件中,每次运行时都会将所有代码加载到内存中,属于一个整体,因此处于同一个代码块的大整数是同一个对象,所以两者id是一样的。

a = '12345'
b = '12345'

print id(a)
print id(b)
-----------------------------
140139908067808
140139908067808


print a is b
-----------------------------
True

 

其他数据类型

如果是其他普通类型对象的新建,python会请求内存,申请内存 。当n1的引用指向其他对象时,原有对象的引用计数会自动减1,没有被引用的对象会立即回收。

 

posted @ 2019-09-10 23:23  金色旭光  阅读(4772)  评论(0编辑  收藏  举报