文章目录
在Python中变量赋值的本质中,我们知道了,在Python中,声明一个变量并赋值的过程实际上是:变量名所代表的内存地址处保存了数据值存储的内存地址,并称该过程为引用。
下面,我们基于上述结论,深入探讨Python中函数参数传递的本质。
1. 问题引入
首先,我们来看一段简单的代码,请你先脑补一下这段代码的输出。
num = 10
nums = [11, 22]
def test(num):
num += 10
def test2(nums):
nums.append(33)
test(num)
test2(nums)
print("调用test函数后,num = ", num)
print("调用test2函数后,nums = ", nums)
实际上,执行完上述代码后,输出为:
调用test函数后,num = 10
调用test2函数后,nums = [11, 22, 33]
即,变量num的值没有被修改成20,但是变量nums被成功追加了33。下面,我们深入探讨一下为什么会有这样的结果。
2. 问题解答
2.1 不可变类型
首先,如上图所示,声明变量并赋值的过程a = 10如Python中变量赋值的本质所述(如上图步骤1)。
其次,定义test函数,并同时声明形参num(实际上,形参变量名可以是任何符合Python编程规范的名称)对应于上图中的步骤2,即:此步骤后,有两个内存地址处(恰巧其别名都是num)存储了相同的数据地址(0x1002)。
然后,如下图所示,当执行了num += 10后,因为Python中数字为不可变类型,所以计算机将:
a. 开辟一块新的内存(地址为0x1004)用以存储数据20;
b. 变量num所代表的地址处存储的数据地址由0x1002变为0x1004。
由此,当最后执行打印语句时,Python解释器所能找到的num仍是代码开始声明赋值的那个(定义在函数内部的变量,其无法在函数外部被访问),而由上图可知,其保存的地址还是0x1002,故取值仍为10。
2.2 可变类型
如上图,对于可变类型,其步骤1、2和上述不可变类型一致。
但区别在于,如下图所示,当执行nums.append(33)时,因为Python中列表是可变类型,所以不会开辟新的内存空间,即两个列表变量的地址处指向了相同的数据地址。
由此,最后执行打印语句时,通过代码开头声明赋值的变量找到的数据地址虽然还是0x1006,但是其值已经被修改成了[11, 22, 33](这也就是所谓数据“可变”的含义)
3. 结论
综上可知:
在Python中,函数传递参数是通过引用的方式,而非数据值传递;
在Python中,可变类型包括列表、字典,不可变类型包括数字、元组、字符串等,故上述现象对这些类型均试用。
点赞
收藏
分享
文章举报
TakingCoding4Granted
发布了37 篇原创文章 · 获赞 1 · 访问量 1282
私信
关注