在Python中,如果将数字、字符串等传入到函数中,再改变其值,我们会发现:当函数结束时,该变量不会发生改变。
In [20]: def q(x):
...: x = 2
...:
In [21]: a = 1
In [22]: q(a)
In [23]: a
Out[23]: 1
我们先令a=1,再在函数中让a的值变为2,当函数结束时,打印a的值,依旧为1。有人称类似于a这样的变量为不可变对象(数字、字符、字符串、元祖等)。
In [24]: def p(x):
...: x[0] = 2
...:
In [25]: b = [1]
In [26]: p(b)
In [27]: b
Out[27]: [2]
这里我们令b是只有一个元素,且该元素值为1的列表,在函数中我们修改了b[0]的值,退出函数后发现b的值被修改了。有人称类似于b这样的变量为可变对象(列表、字典等)。
In [31]: def q(x):
...: print(id(x))
...: x = 2
...: print(id(x))
...:
...:
...:
In [32]: a = 1
In [33]: id(a)
Out[33]: 2002568880
In [34]: q(a)
2002568880
2002568912
In [35]: id(a)
Out[35]: 2002568880
In [36]: id(1)
Out[36]: 2002568880
In [37]: c=1
In [38]: id(c)
Out[38]: 2002568880
那么,在函数中发生了什么?我将用下面的图来表示(用画图画的,有点丑):
所以我们退出函数时,a的值未发生改变。
同样的,我们对b进行分析。假设b是一个长度为100的列表,其中
In [60]: b[0] = 1
In [61]: b[1] = 2
In [62]: b[99] = 2
In [63]: id(b[0])
Out[63]: 2002568880
In [64]: id(b[1])
Out[64]: 2002568912
In [65]: id(b[99])
Out[65]: 2002568912
此时,定义一个函数p,修改b[99]的值
In [73]: def p(x):
...: x[99] = 1
...:
...:
In [74]: b[99]
Out[74]: 2
In [75]: p(b)
In [76]: b[99]
Out[76]: 1
b[99]的值被修改了。
发生了什么?
在调用函数的过程中,首先生成x变量,指向了b指向的内存块。
再对x[99]赋值,指向了1所在的内存块
退出函数之后,x被丢弃,但b依然指向这个列表,而这个列表的内部元素已经被修改了。所以b[99]变成了1。
所以大家应该明白了,为什么数字、字符、字符串、元祖都是值传递,因为你传递进去生成了一个新的变量x,你修改x的值无非是修改了x指向的内存块,而对原变量没有影响。
如果你理解了上面,那么下面的情况你也应该理解了。
In [77]: def t(x):
...: x = [55,66]
...:
In [78]: c = [1,2,3]
In [79]: t(c)
In [80]: c
Out[80]: [1, 2, 3]
因篇幅问题不能全部显示,请点此查看更多更全内容