我做了一个快速测试,以确认使用'='运算符在Python中创建列表的副本实际上是指向它,而不是它自己的副本......
x = [1, 2, 3]
print("x is: " + str(x) + " - " + str(id(x)))
y = x
print("y is: " + str(y) + " - " + str(id(y)))
x = [555, 666]
print("x is NOW: " + str(x))
print("y is NOW: " + str(y))
但结果却结束了......
x is: [1, 2, 3] - [string of numbers]
y is: [1, 2, 3] - [IDENTICAL string of numbers]
x is NOW: [555, 666]
y is NOW: [1, 2, 3]
这似乎表明x和y现在是2个单独的列表?但是它们的对象ID匹配表明它们是相同的内存地址。这似乎不一致,我觉得我错过了一些非常明显的东西!
答案 0 :(得分:2)
Python中的赋值运算符不是分配,它只是设置对象的引用。
这似乎表明x和y现在是2个单独的列表?
是的,那是
[1, 2, 3]
创建一个对象,一个列表,其中包含对象1,2,3。类似地,
[555, 666]
创建另一个包含对象555,666的列表。赋值操作
x = y
只是将指向x指向与相同的对象。没有涉及复制。
我觉得我错过了一些非常明显的东西
要记住的是Python的赋值运算符(=)将左侧变量设置为对象的引用,而对象的分配本身就是一个显式操作。将一个变量分配给另一个变量的值意味着将两个变量设置为指向同一个对象。
但是他们的对象ID匹配表明它们是相同的内存地址。
id()
返回变量指向的对象的id,而不是变量的id。
您永远不能通过将对象赋值给变量来更改对象的值 - 如果您想要更改y
指向的列表的内容,比如说,您必须使用订阅运算符{{1其中[i]
是基于0的索引,例如
i
或者就此而言,列表对象支持的任何值改变操作,例如y[2] = 5
=> [1, 2, 5]
,del
或append
。
如果你想让x和y独立[在评论中提问]
,还有其他一些方法
以下是一些方法
extend
- 如您的示例x = [1, 2, 3]; y = [555, 666]
- 两者都指向具有相同内容的不同列表对象x = [1, 2, 3]; y = list(x)
- 具有不同内容的不同列表对象请注意import copy; x = [[1], [2], [3]]; y = copy.deepcopy(x)
复制列表中包含的每个(可变)对象,而immutable objects不复制但引用相同的对象(即对象1,2,3仍然是即使在deepcopy
之后也是id()
,因为数字是不可变的。)