2017-03-05 48 views
-2

在下面的代码中,为什么w在从v弹出5后仍然保留5将扩展在Python中创建一个新副本

>>> w = [1,2,3] 
>>> v = [4,5] 
>>> w.extend(v) 
>>> w 
[1, 2, 3, 4, 5] 
>>> v 
[4, 5] 
>>> v.pop() 
5 
>>> v 
[4] 
>>> w 
[1, 2, 3, 4, 5] 
+2

而不是尴尬地描述的情况,为什么不张贴代码或解释会话,告诉我们发生了什么和输出不同于你的预期?请给我 – timgeb

+0

[mcve]。你在和我们玩捉迷藏。 –

回答

0

列表的extend方法,接受一个迭代(不仅仅是另一个列表),并延伸与来自可迭代的所有项的列表。

官方Python文档:

通过附加来自可迭代的所有项目扩展列表。等同于[len(a):] =可迭代。

这是比其他迭代手动迭代较短方式,并且append他们原始列表:

v = [1,2,3] 
w = [4,5] 
for i in w: 
    v.append(i) 

这意味着所涉及的项目的基准被从可迭代复制到原始列表,因此稍后修改迭代器(列表w)不会影响原始列表(v)。

要说清楚,这不会改变iterable项目本身的易变性/不可变性。因此,如果来自w的项目是可变的,那么它们在被追加到v(复制参考)后将保持可变。

+0

这是错误的或至少是误导性的。使用扩展时不会复制任何内容。通过执行这个带有可变对象列表的例子来检查自己,然后通过访问其中一个列表来对它们进行变异。 – timgeb

+0

如果第二个迭代中的可变项目被复制,则对它们的引用被复制。因此改变可变项目将反映所有参考。问题是,如果调用'extend'将保持与第二个'list'(传递给'extend')的任何关联,并且我的答案指出答案是否定的,因为“extend”参数不一定是'列表“(可变)。它可以是任何'iterable'(比如一个字符串),所以'extend'方法本身不会保留对迭代器的引用,而是复制它的项目。 – farzad

+0

是的,但扩展不会在可变对象和不可变对象之间产生任何差异。使用'list.extend'时不会复制任何对象。这就是为什么我在编辑帖子之前抱怨过。 – timgeb

0

整数1,2,3,4,5是的某处在内存中并且w指向w.extend(v)之后的所有这些整数。您通过pop方法从v中删除最后一个参考文件的事实不会改变这一点。

0

extend将对象引用添加到列表中。在w.extend(v)之后,这两个列表都引用v中的项目。 v.pop()删除了v的参考文献,但它仍然在w。一旦你扩展了一个列表,从其他容器添加或删除并不重要....这就是引用计数的全部内容。