为了更好的认识函数,我们还要研究值传递问题,再研究这个问题之前,我们已经知道了函数之间的值传递,是实参变量值传递给形参变量,然后让形参变量在函数内完成相应的功能。但是因为数据类型的不同,这里的值传递产生的对实参变量的效果是不同的

1.传递数据本质

参数传递之间传递的肯定是数据,而这种数据本质上是地址值。变量有四个要素:名、值、数据类型、地址值。每个变量在创建时都会在内存中开辟一定空间,该空间具有地址值,并在该地址里面存储数据,Python的变量存储的数据是地址值,该地址值所代表的是真实数据的地址值,而不是变量的地址值。

1.1不可变数据类型

我们之前介绍过数字、字符串、元组它是不可变的,就是说只要在内存中创建了该数据,那么它是不变的,创建了数字1,那么数字1是存在的,我们把变量进行运算操作,假设进行加法运算,让其加1,变为了2,那么这里是创建了一个数字2,数字2也是不可变的,原先的数字1还是存在的,只不过我们的变量中储存的数据是数字2的地址值了。
【python基础】函数-值传递-LMLPHP
图中的0x-xx是地址假想值。
id函数在作用于变量时,其返回的是变量指向数据内容的地址值,编写程序如下所示:
【python基础】函数-值传递-LMLPHP
参数之间数据的传递,就是将实参变量的值赋值给形参变量,这里我们说的实参变量的值就是实参数据的地址值,编写程序如下所示:
【python基础】函数-值传递-LMLPHP
我们通过输出结果发现,num1、num2、num3所存储的地址值都是相同的,都为140716513424168,这说明他们都指向同一个数据,也就是数字1,但是经过运算后,num3所存储的地址值变化了,是因为产生了新数据,新数据的地址赋值给了num3,num3指向了数字2的地址
那么,经过sum函数后,因为num1、num2的地址是没有发生改变的,所以我们输出num1和num2它的结果还是1。
这里我们是用数字举例的,换成字符串、元组等都是同样的道理

1.2可变数据类型

不可变数据类型在内存中的表现:当不可变数据类型(数字、字符串、元组)的变量需要更新新值时,其创建一个新值,将旧值的地址更换为新值的地址,此时指向发生改变。
可变数据类型,我们目前了解的就是列表、字典,我们可以发现它们都不是一个简单的数据,而是一组相对复杂的数据集合,数据集合里面包含的数据类型是任意的,就相当于一个仓库,可变数据类型变量的数据值是仓库的地址,而我们所说的可变数据类型变量里面的数据更新新值时,不是仓库地址的改变,而是仓库内数据元素的改变。
所以,可变数据类型在内存中的表现:当可变数据类型(列表、字典)变量需要更新数据元素新值时,其创建一个数据元素新值,将新值的地址放进可变数据类型所指向的仓库里面,而不是改变可变数据类型变量存储的仓库的地址值,其逻辑如下图所示。
【python基础】函数-值传递-LMLPHP
图中的0x-xx是地址假想值。
我们可以做下验证,编写程序如下所示:
【python基础】函数-值传递-LMLPHP
通过输出结果我们发现,
1.在经过del_first函数之前,输出列表数据元素为[1,2,3,4]。在经过del_first函数之后,输出列表数据元素为[2,3,4]这说明改变了实参变量list所指向的地址中的内容,形象化理解,就是改变了仓库里面的内容。
2.在经过del_first函数之前,list变量所存储的地址值为2113656214912。经过del_first函数之后,list变量所存储的地址值仍为2113656214912。所以说明list变量经过函数操作后,没有改变其存储的地址值,形象化理解,就是没有改变仓库的地址
3.在经过del_first函数之前,列表数据元素0所存储的地址为140712759325480,列表数据元素1所存储的地址为140712759325512。在经过del_first函数之后,列表数据0所存储的地址为原先列表数据元素1存储的地址140712759325512,也就是经过删除第一个数据元素的操作后,所有数据元素都依次往前排列。形象化理解,就是把仓库中第一个位置的物品拿出来,然后把其他的物品依次往前挪一个位置。
这里我们是用列表举例的,换成字典等其他可变数据类型都是同样的道理

1.3总结

不可变数据类型的实参变量,经过函数操作之后,不会改变其原有内容
可变数据类型的实参变量,经过函数操作之后,会改变其原有内容

06-19 10:03