Python复制后列出变异

Python list mutation after copying

def mutation(input_list):
  list_copy = input_list[:]
  list_copy[0] = 10
  input_list = list_copy

# Correctly mutates
sample_list = [0,1,2]
sample_copy = sample_list[:]
sample_copy[0] = 10
sample_list = sample_copy
print(sample_list)

# Incorrectly mutates
sample_list = [0,1,2]
mutation(sample_list)
print(sample_list)

在上面的代码片段中,我复制了一个列表并对其进行了修改。然后我将原件设置为副本,然后它就可以工作了。 让我感到困惑的是,为什么在函数外部执行此过程有效,但如果我在函数内部执行此过程(第二段代码),它会失败?

供参考,代码returns:

[10, 1, 2]
[0, 1, 2]

编辑:我知道调用 input_list[0] = 10 有效。我只想知道这与我首先在内存中显示的有什么不同?

那是因为你为 input_list 设置了新值,它是 mutation 函数的局部变量。

最简单的解决方案是更改作为参数传递的列表的第一个元素的值:

def mutation(input_list):
    input_list[0] = 10

否则你可以编写函数来改变名为 sample_list

的全局变量的值
def mutation():
    global sample_list
    list_copy = sample_list[:]
    list_copy[0] = 10
    sample_list = list_copy

mutation 中,input_list 开始指向与 sample_list 相同的对象,但后来您将其指向 list_copysample_list 未修改。它仍然指向原始对象。

当您在函数之外执行此操作时,您会更改 sample_list 以在打印之前指向新对象。

我认为使用内置函数 id 来显示对象 ID 会有所帮助。如果两个变量名的 ID 给出相同的结果,那么它们指的是同一个对象;否则对象不同。

>>> def mutation(input_list):
...     print(id(input_list))
...     list_copy = input_list[:]
...     print(id(list_copy))
...     input_list = list_copy
...     print(id(input_list))
...     
>>> a = list(range(10))
>>> print(id(a))
140737233394376
>>> mutation(a)
140737233394376
140737233289160
140737233289160

在上面,我们看到在input_list = list_copy之后,名字input_listlist_copy在内存中指代的是同一个对象,也就是说不再指代列表作为函数参数给出。这就是您期望的突变不起作用的原因 - 您正在修改一个完全不同的对象。