7.31 改变参数的值
如果将一个变量作为参数传入函数,并且在函数内部改变这个变量的值,那么结果会怎么样呢?我们现在来试验一下。
x = 20
s = '世界你好'
def test(x,s):
x = 40
s = 'Hello World'
test(x,s)
print(x,s)
输出结果:
20 世界你好
在上面的代码中,首先定义了两个变量:x和s,然后将其传入test函数,并在该函数中修改这两个变量的值。最后再函数外部输出这两个变量,得到的结果是它们的值并没有改变。所以说,对于数值类型、字符串类型等一些简单类型,在函数内部可以修改变量的值,但不会影响到原始变量的值。也就是说,函数内部操作的参数变量实际上是x和s的一个副本。将变量传入函数,并修改变量值的过程与下面的代码类似。
x = 20
s = '世界你好'
#下面的代码相当于函数内部的操作
x1 = x #x1是x的副本,相当于将x传入函数
s1 = s #s1是s的副本,相当于将s传入函数
x1 = 40
s1 = 'Hello World'
#这里相当于退出函数,在函数外部输出x变量和s变量
print(x,s)
输出结果:
20 世界你好
上面这段代码和之前那段代码输出的结果是一样的。
现在再来看看下面的代码。这段代码中,变量x和变量y的数据类型分别是字典和列表。
x = {
'a':30,'b':20}
y = ['a','b','c']
def test(x,y):
x['a'] = 100
y[1] = 'abcd'
test(x,y)
print(x,y)
输出结果:
{'a': 100, 'b': 20} ['a', 'abcd', 'c']
可以看到,如果将字典和列表变量传入函数,在函数内部修改字典和列表变量的值,是可以影响x变量和y变量的。这就涉及一个值传递和引用传递的问题。如果传递的变量类型是数值、字符串、布尔等类型,那么就是值传递;如果传递的变量类型是序列、对象等复合类型,就是引用传递。
值传递就是在传递时将自身复制一份,而在函数内部接触到的参数实际上是传递给函数的变量的副本,修改副本的值自然不会影响到原始变量。而像序列、对象这样的复合类型的变量,在传入函数时,实际上也将其复制了一份,但复制的不是变量中的数据,而是变量的引用。因为这些复合类型在内存是用一块连续或不连续的内存空间保存的,要想找到这些复合类型的数据,必须得到这些内存空间的首地址,而这个首地址就是复合类型数据的引用。因此,如果将复合类型的变量传入函数,复制的是内存空间的首地址,而不是首地址指向的内存空间本身。对于本例来说,在函数内部访问的x和y与在函数外部定义的x和y指向同一个内存空间,所以修改内存空间中的数据,自然就会影响到函数外部的x变量和y变量中的值。
现在已经知道了,如果