这是我的第一个问题,所以如果我是一个完整的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个小时但仍然看不到它。
感谢您的帮助!
答案 0 :(得分:7)
在您的函数中,z
和spins
引用相同的列表,该列表也称为spin
的全局名称。如果您修改了一个,那么通过其他名称也可以看到这些更改。变量z
是多余的。
如果您希望z
成为spins
的副本,那么就这样做:
z = spins[:]
或:
z = list(spins)
答案 1 :(得分:1)
您忘记的是z
和spins
本质上是同一个对象。两者都指向相同的列表并具有相同的元素。
例如:
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中,所有对象都由指针引用。所有变量名称(如spin
和test
)都只是指针。当您将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