删除列表的不同方法

时间:2015-04-22 23:14:25

标签: python list memory-management

我想了解原因:

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

表现得如此不同。

我为每个人进行了测试,以说明我目睹的差异:

>>> # 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
[]

我确实找到Different ways of clearing lists,但我没有找到行为差异的解释。任何人都可以澄清这个吗?

6 个答案:

答案 0 :(得分:25)

测试1

>>> 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

测试2

>>> 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

测试3

>>> 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  

答案 1 :(得分:15)

在您的三种&#34;删除Python列表&#34; 的方法中,只有一个实际上改变了原始列表对象;另外两个只影响名称

  1. a = []创建新列表对象,并将其分配给名称a
  2. del a删除名称它所引用的对象。
  3. del a[:]从名称a引用的列表中删除所有引用(尽管类似地,它并不直接影响从引用的对象中引用的对象列表)。
  4. 可能值得阅读关于Python名称和值的this article,以便更好地了解这里发生的事情。

答案 2 :(得分:7)

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

Test 2:您将名称a删除,以便它不再存在,但您仍然可以使用b对内存中的对象进行引用。

Test 3 a[:]就像复制列表或想要更改列表的所有元素一样,是指对列表中存储的对象的引用,而不是名称ab也会被清除,因为它是a的引用,因此对a内容的更改将影响b

行为是documented

  

有一种方法可以从给定索引的列表中删除项目   它的价值: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也可用于删除整个变量:

>>>
>>> del a
     

以后引用名称a是一个错误(至少在另一个之前   值被分配给它)。我们稍后会找到del的其他用途。

因此,只有del a实际删除aa = []将a重新绑定到新对象,del a[:]清除a。在第二次测试中,如果b没有对该对象的引用,那么它将被垃圾收集。

答案 3 :(得分:5)

del a

正从范围中删除变量a。引自python docs

  

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

del a[:]

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

  

传递删除属性引用,订阅和切片   涉及的主要对象;通常删除切片   相当于分配一个正确类型的空切片(但是甚至   这是由切片的对象确定的。

答案 4 :(得分:3)

在这三种方法中,只有第三种方法实际上会导致删除“&#39; a&#39;指着。让我们快速概述一下。

当你正确a = [1, 2, 3]时,它会在内存中创建一个列表,其中包含[1,2,3]项,然后获取&#39; a&#39;指向它。当你写b = a这个预制品时,会发现什么?称为“浅色副本”,#39;即它使&#39; b&#39;指向同一块内存和&#39; a。&#39;深拷贝将涉及将列表的内容复制到新的内存块中,然后指向该内容。

现在,当您撰写a = []时,您正在创建一个新的列表,其中没有任何项目,并且正在创建一个&#39;指向它。原始列表仍然存在,并且&#39; b&#39;指着它。

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

最后,del a[:]会查看数据&#39; a&#39;指向并清空它的内容。 &#39;一个&#39;仍然存在,所以你可以使用它。 &#39; B&#39;也存在,但它指向同一个空列表&#39; a&#39;是的,这就是它给出相同输出的原因。

答案 5 :(得分:0)

要了解删除列表的不同方法之间的区别,让我们在图片的帮助下逐一查看每个列表。

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

创建新的列表对象并将其分配给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

这会从范围中删除变量a1。这里,只删除变量a1,原始列表仍然存在于内存中。 a2仍然指向a1过去指向的原始列表。如果我们现在尝试访问a1,我们将获得NameError