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没有产生影响。

发表回复

您的电子邮箱地址不会被公开。