python中修改形参对实参的影响及解决办法
问题描述
今天在做项目的时候遇到了一个“小坑”,就是当函数的形参是列表对象时,python的语法特性会使得函数对形参列表的修改直接影响到实参上。
例如下面的测试代码:
a = [1,2,3]
def test(x):
x[0] = 100
print(x,id(x))
print(a,id(a))
test(a)
print(a,id(a))
输出结果:
[1, 2, 3] 2319344820872
[100, 2, 3] 2319344820872
[100, 2, 3] 2319344820872
从上面结果可以看出,确实对形参列表的修改直接改掉了实参。
那么我们可以想,那我能不能事先先存一个备份列表,然后每次执行完函数后再改过来,我们来尝试一下。增加一个backup列表作为备份。
a = [1,2,3]
backup = a
def test(x):
x[0] = 100
print(x,id(x))
print(a,id(a))
test(a)
a = backup
print(a,id(a))
print(backup,id(backup))
输出结果
[1, 2, 3] 1855735550664
[100, 2, 3] 1855735550664
[100, 2, 3] 1855735550664
[100, 2, 3] 1855735550664
我们发现并没有奏效,开的backup列表与原本的a列表应该是指向同一片内存的,只是名称不同,修改的时候两者其实都被修改了。
解决方法
def test(a) :
a[0] = 6
print("a =",a,id(a))
c = [1,2,3]
#方法一:传副本过去
test(c.copy())
#方法二:
test(c[:])
print("c =",c,id(c))
对于一般的数值型的数据,python函数对形参的修改不会影响实参!
自定义一个测试函数,通过对比形参和实参的ID来研究修改形参对实参的影响。
def test(a) :
print("a =",a,id(a))
c = 20
test(c)
print("c =",c,id(c))
输出结果
a = 20 140707504189792
c = 20 140707504189792
传参后a和c的id相同,说明a和c指向同一对象。接下来对a进行重新赋值。
def test(a) :
a = 10
print("a =",a,id(a))
c = 20
test(c)
print("c =",c,id(c))
输出结果
a = 10 140707504189472
c = 20 140707504189792
a的值和id已经发生了改变,但是c没有发生变化,说明对a重新赋值过程中,系统新建了一个对象,a指向了新的对象,且对c没有产生影响。