引用赋值,只是将一个变量的引用赋给另外一个变量,两个变量指向同一块内存,所以修改一个,另外一个也会受影响。
对于可变对象的函数传参,未做处理的情况下,实际是将引用传入函数。即将实参的引用赋值给了形参。
def add_element(arr):
arr.append(100)
print("函数处理过的参数:", arr)
a = [1, 2, 3]
print("传参前的a:", a)
add_element(a)
print("传参后的a:", a)
运行结果:
python chapter3.py
传参前的a: [1, 2, 3]
函数处理过的参数: [1, 2, 3, 100]
传参后的a: [1, 2, 3, 100]
可见,在函数内对可变对象进行处理,会同步影响函数外的变量内容。
如果想杜绝这种现象,就要将可变对象进行处理传给函数。
1. add_element(a[:])
2. add_element(list(a))
3. add_element(a.copy())
4. import copy
add_element(copy.copy(a))
以上四种方法,都是对a处理,生成了一个新的列表传入函数,以此实现值传递。
>>> a = [1, 2]
>>> e = a # 引用赋值
>>> e.append(3)
>>> e
[1, 2, 3]
>>> a
[1, 2, 3]
>>> b = a.copy()
>>> b
[1, 2, 3]
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3]
>>> c = a[:]
>>> c
[1, 2, 3, 4]
>>> c.append(5)
>>> c
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4]
>>> import copy
>>> d = copy.copy(a)
>>> d
[1, 2, 3, 4]
>>> d.append(6)
>>> d
[1, 2, 3, 4, 6]
>>> a
[1, 2, 3, 4]
不可变对象传入函数,实际也是引用传递,但是对不可变对象做操作的话,会生成新的地址来保存结果。
a = 500
print("运算前的a:", a)
print("运算前a的地址:", id(a))
def add(a):
print("传入函数后运算前a的地址:", id(a))
a += 50 # 在对不可变对象操作的时候,会生成一个新的变量来存储结果(不可变对象的值不同,代表在内存中的地址也不一样)
print("运算后a的地址:", id(a))
print("运算后的a:", a)
add(a)
print("调用函数后的a: ", a)
运行结果:
python chapter3.py
运算前的a: 500
运算前a的地址: 4568288528
传入函数后运算前a的地址: 4568288528
运算后a的地址: 4566421168
运算后的a: 550
调用函数后的a: 500