不同的方式删除列表

我想明白为什么:

  • a = [] ;
  • del a ; 和
  • del a[:] ;

performance如此不同。

我对每个人都进行了testing,以说明我所见证的差异:

 >>> # Test 1: Reset with a = [] ... >>> a = [1,2,3] >>> b = a >>> a = [] >>> a [] >>> b [1, 2, 3] >>> >>> # Test 2: Reset with del a ... >>> a = [1,2,3] >>> b = a >>> del a >>> a Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined >>> b [1, 2, 3] >>> >>> # Test 3: Reset with del a[:] ... >>> a = [1,2,3] >>> b = a >>> del a[:] >>> a [] >>> b [] 

我的确发现了清单清单的不同方式 ,但我没有find对行为差异的解释。 任何人都可以澄清这一点?

testing1

 >>> a = [1,2,3] # set a to point to a list [1, 2, 3] >>> b = a # set b to what a is currently pointing at >>> a = [] # now you set a to point to an empty list # Step 1: A --> [1 2 3] # Step 2: A --> [1 2 3] <-- B # Step 3: A --> [ ] [1 2 3] <-- B # at this point a points to a new empty list # whereas b points to the original list of a 

testing2

 >>> a = [1,2,3] # set a to point to a list [1, 2, 3] >>> b = a # set b to what a is currently pointing at >>> del a # delete the reference from a to the list # Step 1: A --> [1 2 3] # Step 2: A --> [1 2 3] <-- B # Step 3: [1 2 3] <-- B # so a no longer exists because the reference # was destroyed but b is not affected because # b still points to the original list 

testing3

 >>> a = [1,2,3] # set a to point to a list [1, 2, 3] >>> b = a # set b to what a is currently pointing at >>> del a[:] # delete the contents of the original # Step 1: A --> [1 2 3] # Step 2: A --> [1 2 3] <-- B # Step 2: A --> [ ] <-- B # both a and b are empty because they were pointing # to the same list whose elements were just removed 

在你的三种“删除Python列表”的方法中只有一个实际上改变了原来的列表对象; 另外两个只影响名字

  1. a = []创build一个新的列表对象 ,并将其分配给名称a
  2. 删除名称而不是它引用的对象。
  3. del a[:]删除名称a 引用的列表中的所有引用 (尽pipe同样,它不会直接影响从列表中引用的对象)。

可能值得阅读这篇关于Python名字和值的文章 ,以更好地理解这里发生了什么。

Test 1:重新绑定a新对象, b仍然保存对原始对象的引用a只是通过重新绑定到一个新对象的名称不会更改b指向的原始对象。

Test 2:你删除了名字a所以它不再存在,但是你仍然有一个对b的对象的引用。

Test 3 a[:]就像当你复制一个列表或者想要改变一个列表的所有元素一样,引用的是存储在列表中的对象而不是名字ab也被清除,因为它又是一个对a意志效应b的内容的改变。

行为被logging :

有一种方法可以从列表中删除一个项目给它的索引,而不是它的值: del语句。 这不同于返回值的pop()方法。 del语句也可以用来从列表中删除切片或清除整个列表(我们之前通过将空列表分配给切片)。 例如:

 >>> >>> a = [-1, 1, 66.25, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.25, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.25, 1234.5] >>> del a[:] >>> a [] 

del也可以用来删除整个variables:

 >>> >>> del a 

以后引用这个名字是一个错误(至less直到另外一个值被分配给它)。 之后我们会发现del其他用途。

所以只有del a实际上删除aa = []将a重新绑定到一个新的对象, del a[:]清除a 。 在你的第二个testing中,如果b没有引用该对象,它将被垃圾收集。

 del a 

从范围中删除variablesa 。 从python文档引用:

删除名称将删除该名称与本地或全局名称空间的绑定,具体取决于名称是否出现在同一代码块中的全局语句中。

 del a[:] 

只是删除一个的内容,因为删除被传递给a对象,而不是应用到它。 再次从文档:

属性引用,订阅和切片的删除被传递给涉及的主对象; 删除切片通常相当于分配了正确types的空片(即使这是由切片对象决定的)。

在这三种方法中,只有第三种方法实际上导致删除“a”指向的列表。 让我们做一个快速的概述。

当你正确的a = [1, 2, 3]它会在内存中创build一个列表,其中的项目[1,2,3]然后得到'a'指向它。 当你写b = a这会形成什么叫做“浅拷贝”,也就是说,“b”指向与“a”相同的内存块。 深度复制将涉及将列表的内容复制到新的内存块中,然后指向该内存块。

现在,当你写a = []你正在创build一个没有任何项目的新列表,并得到'a'指向它。 原始列表仍然存在,'b'指向它。

在第二种情况下, del a删除指向[1,2,3]的指针而不是它自己的数组。 这意味着b仍然可以指向它。

最后, del a[:]通过数据“a”指向并清空它的内容。 “a”依然存在,所以你可以使用它。 'b'也存在,但它指向同一个空列表'a',这就是为什么它给出相同的输出。

要理解删除列表的不同方式之间的区别,让我们逐一在图片的帮助下看到它们。

 >>> a1 = [1,2,3] 

新的列表对象被创build并被分配给a1

I1

 >>> a2 = a1 

我们将a1分配给a2 。 所以,列表a2现在指向a1指向的列表对象。

I2

下面解释的不同方法:

方法1使用[]

 >>> a1 = [] 

I3

在为a1分配一个空列表时,对a2没有影响。 a2仍然指向相同的列表对象,但a1现在指的是一个空列表。

方法2使用del [:]

 >>> del a1[:] 

I4

这将删除a1指向的列表对象的所有内容。 现在a1指向一个空的列表。 由于a2也是指同一个列表对象,它也变成了一个空列表。

方法3使用del a1

 >>> del a1 >>> a1 NameError: name 'a1' is not defined 

I5

这将从作用域中删除variablesa1 。 在这里,只是variablesa1被删除,原始列表仍然存在于内存中。 a2仍指向a1用来指向的原始列表。 如果我们现在尝试访问a1 ,我们将得到一个NameError