Python函数参数不是deepcopies

时间:2019-07-05 02:33:51

标签: python python-3.x

我有两个功能相同,但为看起来像这样的不同值设置值

indices = [x for x in range(26)]
reflector = [0 for x in range(26)]
wiring = [0 for x in range(26)]

def generate_r(ind=indices,rf=reflector):
    while len(ind) > 0:
        smp = sample(ind, 2)
        for elt in smp:
            ind.remove(elt)
        rf[smp[0]] = smp[1]
        rf[smp[1]] = smp[0]

    return rf

def generate_w(ind=indices,wr=wiring):
    while len(ind) > 0:
        smp = sample(ind, 2)
        for elt in smp:
            ind.remove(elt)
        wr[smp[0]] = smp[1]
        wr[smp[1]] = smp[0]
        print(wr)
    return wr

我会期望的

generate_r()
generate_w()

要给我返回两个包含0至25之间的26个不同值的列表。但是,我发现反射器是我想要的列表,而w仍然是全0的列表。

检查后,我发现在运行generate_r()之后索引为空,这使我认为python并未将索引副本传递给函数,而是传递了对同一对象的引用。这是怎么回事吗?如果是这样,是否有一种方法可以使函数的本地名称空间获得自己的副本,而无需在函数本身中创建?

2 个答案:

答案 0 :(得分:3)

furas已经为您提供了解决方案。以下是发生这种情况的原因。

>>> def increment(n):
...   n.append([4])
>>> L = [1, 2, 3]
>>> increment(L)
>>> print(L)
L = [1, 2, 3, 4]   # a changed!

代码L = [1, 2, 3]的变量L引用列表对象,其中包含对三个不可变对象的引用:整数1、2和3。

enter image description here

像往常一样,当我们将L传递给increment()时,该函数将局部变量n指向与L相同的对象:

enter image description here

.append()方法会修改列表,因为列表是可变的:

enter image description here

由于没有创建新对象并且更改发生在该对象上,因此当我们打印L时,我们将获得修改后的列表。

答案 1 :(得分:0)

一个适合您的解决方案:

from random import sample

indices = list(range(26))
reflector = [0] * 26
wiring = reflector[:]

def generate_r(ind=indices[:], rf=reflector):
    while len(ind) > 0:
        smp = sample(ind, 2)
        for elt in smp:
            ind.remove(elt)
        rf[smp[0]] = smp[1]
        rf[smp[1]] = smp[0]

    return rf

def generate_w(ind=indices[:], wr=wiring):
    while len(ind) > 0:
        smp = sample(ind, 2)
        for elt in smp:
            ind.remove(elt)
        wr[smp[0]] = smp[1]
        wr[smp[1]] = smp[0]
    return wr

print(generate_r())
print(generate_w())