Python 何时知道初始化是一个副本,以便在一个地方的更改自动地改变另一个地方?
Python 何时知道初始化是一个副本,以便在一个地方的更改自动地改变另一个地方?
如果我执行:
x = 1 y = [x,x,x,x] y[1] = 2 print y
我得到的结果是:
[1,2,1,1]
但是如果我执行:
x = [1,1] y = [x,x,x,x] y[1][0] = 2 print y
我得到的结果是:
[[2,1],[2,1],[2,1],[2,1]]
有人能解释一下这两者之间的微妙差别吗?我的意思是,比如Python如何分配内存,以至于在第一种情况下,y的四个元素读取不同的内存位置,但在第二种情况下,y的四个元素读取相同的位置?
而且为什么Python会表现出这种行为?因为我使用Matlab时,不会出现这样的情况。
谢谢。
问题的原因是在第一个例子中,您正在更改y
的内容,而在第二个例子中,您正在更改y
内的列表的内容。
解决方法是使用深拷贝而不是浅拷贝来创建y
的副本。这样,当更改一个位置时,另一个位置也会自动更改。您可以使用copy
模块中的deepcopy
函数来实现深拷贝。
以下是修改后的代码示例:
import copy x = 1 y = [x, x, x, x] print(map(id, y)) x = [1, 1] y = copy.deepcopy([x, x, x, x]) print(map(id, y))
输出结果:
[41548904, 41548904, 41548904, 41548904] [50255344, 50255344, 50255344, 50255344]
注意到两个列表都有4个相同的对象,现在尝试:
x = 1 y = [x, x, x, x] y[1] = 2 print(map(id, y)) x = [1, 1] y = copy.deepcopy([x, x, x, x]) y[1] = [2, 1] print(map(id, y))
输出结果:
[28224616, 28224592, 28224616, 28224616] [36931056, 36929264, 36931056, 36931056]
注意到您在两个示例中都更改了列表y
的一个元素。
最后,如果您执行以下操作:
x = [1, 1] y = [x, x, x, x] y[1][0] = 2
您正在更改位置1
上的元素的内容,该位置指向x(与所有其他位置一样),因此当您打印y
时,将打印四次具有其第一个值更改的x
。
假设x是一个列表。如果我执行id(x)
,我会得到指针id,但如果我执行map(id,x)
,我会得到x指向的内容的id。我对吗?
id
返回Python对象的内部id,每个活动对象的id都是唯一的。请阅读这个。