populating lists — what is python doing?
我想我已经解决了我自己的问题,但我正在寻求更好的理解为什么,或者是开明/直截了当。
我有一个列表,我称之为vec:
1 | vec = [0.0, 0.0] |
在读取数据时更改值。
为了比较当前值和以前的值,我有另一个列表,我称之为oldvec。如果我把oldvec定义为
1 | oldvec = vec |
然后,每次vec更改值时,它都会更改值,所以比较是无用的——它们总是相同的。
但是,如果我改为写
1 | oldvec = [vv for vv in vec] |
我没有这个问题——oldvec在vec改变的时候保持它的值,所以当前和以前的向量之间的比较是按我需要的方式工作的,也就是说,它实际上检测重复和不重复!…为什么?
你能看到引擎盖下面发生了什么的一种方法是使用
如果我们为这三个命令运行它,并查看不同的地址(这只是在我的计算机上;如果您自己运行它,您将获得不同的号码):
1 2 3 4 5 6 7 8 9 10 11 | >>> vec = [0.0, 0.0] >>> print id(vec) 4501729936 >>> oldvec1 = vec >>> print id(oldvec1) 4501729936 >>> oldvec2 = [vv for vv in vec] >>> print id(oldvec2) 4502046984 |
我们看到
相比之下,
这是一张很快的脏照片来显示发生了什么。虽然红色blob和绿色blog恰好包含相同的信息,但它们是两个不同的blob。
将oldvec设置为vec实际上使oldvec指向vec。您没有创建新的列表,只是为它取了另一个名称。通过使用列表理解,您可以显式地创建列表的新副本,相当于vec.copy()。
您应该将python列表看作一个对象:在内存中的某个地方实例化的对象,其中有一个或多个指针存储其内存地址——也就是说,当您说
让我举例说明一下:例如,假设您的列表
现在,想想你的新品:
希望有帮助。
在Python中,变量是"引用",这意味着可以有两个变量引用同一个对象。在您的第一个示例中,正在发生的事情是:同一个列表有两个名称。
如果您需要第二个实际列表,可以"复制"第一个列表。有关方法,请参见此处:如何克隆或复制列表?
请注意,这也适用于列表中的项目——如果它们是更复杂的对象,您可以选择对列表进行"深度复制",复制每个元素的每个单独部分,或者只复制引用"浅复制",这样您就有了一个包含对原始对象新引用的新列表。您需要为每个用例选择正确的方法。