Python中变量在内存的存储与地址变化
- 首先,最重要的,你需要知道,在Python中,变量保存的仅为值的引用,即变量是内存及其地址的抽象
- 在Python中,变量的存储采用了引用语义的方式,变量在内存之中所存储的仅仅为变量的值所在的内存地址,而非值本身(可以理解为,变量中存储的是地址)
- Python支持相同的值的不同对象,相当于内存中对于同值的对象保存了多份,但是这只是对于可变数据类型适用,对于不可变数据类型,内存中只能有一个相同值的对象
引用语义
采用引用语义的方式:
- 存储变量所需要的存储空间大小一致,因为变量仅仅保存了一个引用
- 也被称为对象语义和指针语义
- 变量的每一次初始化,都会开辟一个新的存储空间,并将新的内容的地址赋值给变量。
- 对于Python中的复杂数据类型(如:列表、元组、字典等),如果仅仅是对其中的一个或多个元素进行修改,并不会改变其地址,如果进行删除或者添加操作,也只是单纯的改变内部元素的地址引用,但是,如果对整体进行重新赋值,那么就会对这些复杂数据类型重新赋予一个新的地址,来覆盖之前的地址,也只有在这种情况下,这些复杂数据类型的地址才会发生改变
值语义
- 有些语言并不是采用的如上的存储方式,而是直接把变量的值保存在变量的存储区域里面,这种方式我们称之为值语义。
- 最为典型的就是C语言
- 采用值语义:
- 每一个变量在内存中所占空间就需要根据变量的实际大小来决定
可变数据类型与不可变数据类型
-
可变数据类型
- 列表
list
- 字典
dict
- 列表
-
不可变数据类型
- 整型
int
- 浮点型
float
- 字符串型
str
- 元组
tuple
- 整型
-
不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,就是不可变数据类型引用的地址的值不可改变
改变对象的值,其实是引用了不同的对象
-
可变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址不会改变,只是对应地址的内容改变或者地址发生了扩充,所以对于相同的值的不同对象,会存在多份,即每个对象都有自己的地址
引用传递和值传递
值传递
- 简单来说,对于函数输入的参数对象,函数执行中首先生成一个对象的副本,并在执行过程中对副本进行操作,也就是说,函数执行结束之后,对象并不会发生任何变化,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。
- 值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(被调函数新开辟内存空间存放的是实参的副本值)
引用传递
- 当传递列表或者字典时,如果改变引用的值,就修改了原始的对象。(被调函数新开辟内存空间存放的是实参的地址)
- 注意:在函数调用中无法直接修改整个列表或字典的值 如果这样做,就是相当于也是相当于创建副本的值传递