6

这是我的第一个问题,所以如果我是一个完全的 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 个小时,仍然看不到它。

谢谢你的帮助!

4

6 回答 6

10

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

如果您想z成为副本spins那么只需执行以下操作:

z = spins[:]

或者:

z = list(spins)
于 2013-09-22T23:48:01.413 回答
2

你忘记的事情是,z本质spins上是同一个对象。两者都指向同一个列表并具有相同的元素。

例如:

a = [0]
b = a

b[0] = 1
print a

结果:

[1]

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

a = [0]
b = a[:]

b[0] = 1
print a

结果:

[0]
于 2013-09-22T23:48:35.073 回答
2

In Python, all objects are referenced by pointers. All variable names like spin and test are just pointers. When you assign spin to z you are just making z point to the same object as spin and then mutating the object pointed to by z (which is the same as the object pointed to by spin).

All function calls in Python are pass-by-value where the values are direct references to objects. Thus, if you mutate a list object within a function, it will appear mutated even after you return from the function.

You have to create a new copy of the list if you don't want to accidentally mutate spin. Other answers have shown ways of copying a list. I personally like the [:] syntax that kindall showed in his answer.

于 2013-09-22T23:52:41.833 回答
0
z = spins

将两个名称放在同一个对象上。这也会发生,num = old_num但是因为你永远不能就地更改数字(它们是不可变的),所以就像number = number * -1给出number * -1标签number并删除旧的一样。

当你这样做

z[j] = ...

you're changing z, not assigning, which is why this changes both of the labelled items. What you want to do is make a copy, which you can do like:

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

All of which are equally valid. Because this is a new item, changing it does not affect the original.

于 2013-09-22T23:50:45.780 回答
0

Another way to create a new list is to use a list comprehension

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

Multiply by -1 can also just be -e so

def flip(spins, j):
    return [-e if i == j else e for i, e in enumerate(spins)]
于 2013-09-23T00:03:06.083 回答
0

Python treats mutable (list, dictionary, pandas dataframe and series) and immutable (int, tuple, float) data types differently as they get processed inside a function.

Immutable data type gets changed even if it's used inside a function. To avoid this, always make sure to do the processing on the copy of the data by calling .copy() method which creates a copy of the data in a new location.

.copy() works with all the above mentioned mutable data types.

This code will do the job for you:

def flip(spins,j):
    z = spins.copy()
    z[j] = z[j]*-1
    return z
于 2020-08-05T20:22:56.547 回答