Python函数正在改变我的输入值,我无法弄清楚为什么

时间:2013-09-22 23:44:18

标签: python function input

这是我的第一个问题,所以如果我是一个完整的dweeb帖子,请告诉我为什么以及如何在将来避免它!

我有一些python代码应该只取一个列表,然后将第j个分量乘以-1。这是有问题的代码。

def flip(spins,j):
    z = spins
    z[j] = z[j]*-1
    return z

然而,我注意到的是,如果我尝试做类似

的事情
spin = [1,1,1]
test = flip(spin,1)

它会将正确的值[1,-1,1]分配给'test',但它也会将'spin'的值更改为[1,-1,1]。我知道必须有一些我完全可以忽略的东西,但是我已经盯着它看了2个小时但仍然看不到它。

感谢您的帮助!

6 个答案:

答案 0 :(得分:7)

在您的函数中,zspins引用相同的列表,该列表也称为spin的全局名称。如果您修改了一个,那么通过其他名称也可以看到这些更改。变量z是多余的。

如果您希望z成为spins副本,那么就这样做:

z = spins[:]

或:

z = list(spins)

答案 1 :(得分:1)

您忘记的是zspins本质上是同一个对象。两者都指向相同的列表并具有相同的元素。

例如:

a = [0]
b = a

b[0] = 1
print a

结果:

[1]

要复制列表,请尝试以下操作:

a = [0]
b = a[:]

b[0] = 1
print a

结果:

[0]

答案 2 :(得分:0)

z = spins

将两个名称放在同一个对象上。 num = old_num也会发生这种情况,但由于您永远无法就地更改数字(它们是不可变的),number = number * -1之类的内容只会number * -1标记为number并删除旧版本之一。

当你这样做时

z[j] = ...

您正在更改z,而不是分配,这就是为什么这会更改标记项目的两个。你想要做的是复制,你可以这样做:

z = spins[:]     # Traditional way
z = spins(spins) # Pragmatic way
z = spins.copy() # My favorite way

所有这些都同样有效。因为这是一个新项目,更改它不会影响原始项目。

答案 3 :(得分:0)

在Python中,所有对象都由指针引用。所有变量名称(如spintest)都只是指针。当您将spin分配给z时,您只是将z指向与spin相同的对象,然后改变z指向的对象(这是与spin)指向的对象相同。

Python中的所有函数调用都是值传递,其中值是对象的直接引用。因此,如果在函数中改变列表对象,即使从函数返回后它也会突变。

如果您不想意外改变spin,则必须创建列表的新副本。其他答案已经显示了复制列表的方法。我个人喜欢他的答案中显示的[:]语法。

答案 4 :(得分:0)

创建新列表的另一种方法是使用列表推导

def flip(spins, j):
    return [e * -1 if i == j else e for i, e in enumerate(spins)]

乘以-1也可以-e所以

def flip(spins, j):
    return [-e if i == j else e for i, e in enumerate(spins)]

答案 5 :(得分:0)

Python在函数中处理可变数据(列表,字典,pandas数据框和序列)和不可变数据(int,元组,浮点数)的方式有所不同。

不可修改的数据类型即使在函数内部使用也被更改。为避免这种情况,请始终确保通过调用.copy()方法对数据副本进行处理,该方法将在新位置创建数据副本。

.copy()适用于上述所有可变数据类型。

此代码将为您完成这项工作:

def flip(spins,j):
    z = spins.copy()
    z[j] = z[j]*-1
    return z