Different ways of deleting lists

Question:

I want to understand why:

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

behave so differently.

I ran a test for each to illustrate the differences I witnessed:

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

I did find Different ways of clearing lists, but I didn’t find an explanation for the differences in behaviour. Can anyone clarify this?

Asked By: grasswistle

||

Answers:

Test 1: rebinds a to a new object, b still holds a reference to the original object, a is just a name by rebinding a to a new object does not change the original object that b points to.

Test 2: you del the name a so it no longer exists but again you still have a reference to the object in memory with b.

Test 3 a[:] just like when you copy a list or want to change all the elements of a list refers to references to the objects stored in the list not the name a. b gets cleared also as again it is a reference to a so changes to the content of a will effect b.

The behaviour is documented:

There is a way to remove an item from a list given its index instead
of its value: the del statement. This differs from the pop()
method which returns a value. The del statement can also be used to
remove slices from a list or clear the entire list (which we did
earlier by assignment of an empty list to the slice). For example:

>>>
>>> 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 can also be used to delete entire variables:

>>>
>>> del a

Referencing the name a hereafter is an error (at least until another
value is assigned to it). We’ll find other uses for del later.

So only del a actually deletes a, a = [] rebinds a to a new object and del a[:] clears a. In your second test if b did not hold a reference to the object it would be garbage collected.

Answered By: Padraic Cunningham
del a

is removing the variable a from the scope. Quoting from python docs:

Deletion of a name removes the binding of that name from the local or
global namespace, depending on whether the name occurs in a global
statement in the same code block.

del a[:]

is simply removing the contents of a, since the deletion is passed to the a object, instead of applied to it. Again from the docs:

Deletion of attribute references, subscriptions and slicings is passed
to the primary object involved; deletion of a slicing is in general
equivalent to assignment of an empty slice of the right type (but even
this is determined by the sliced object).

.

Answered By: ODiogoSilva

Test 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

Test 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

Test 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  
Answered By: Malik Brahimi

Of your three “ways of deleting Python lists”, only one actually alters the original list object; the other two only affect the name.

  1. a = [] creates a new list object, and assigns it to the name a.
  2. del a deletes the name, not the object it refers to.
  3. del a[:] deletes all references from the list referenced by the name a (although, similarly, it doesn’t directly affect the objects that were referenced from the list).

It’s probably worth reading this article on Python names and values to better understand what’s going on here.

Answered By: jonrsharpe

Of those three methods, only the third method actually results in deleting the list that ‘a’ points to. Lets do a quick overview.

When you right a = [1, 2, 3] it creates a list in memory, with the items [1, 2, 3] and then gets ‘a’ to point to it. When you write b = a this preforms whats’ called a ‘shallow copy,’ i.e. it makes ‘b’ point to the same block of memory as ‘a.’ a deep copy would involve copying the contents of the list into a new block of memory, then pointing to that.

now, when you write a = [] you are creating a new list with no items in it, and getting ‘a’ to point to it. the original list still exists, and ‘b’ is pointing to it.

in the second case, del a deletes the pointer to [1,2,3] and not the array it’s self. this means b can still point to it.

lastly, del a[:] goes through the data ‘a’ is pointing to and empties it’s contents. ‘a’ still exists, so you can use it. ‘b’ also exists, but it points to the same empty list ‘a’ does, which is why it gives the same output.

Answered By: Psymunn

To understand the difference between different ways of deleting lists, let us see each of them one by one with the help of images.

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

A new list object is created and assigned to a1.

i1

>>> a2 = a1

We assign a1 to a2. So, list a2 now points to the list object to which a1 points to.

i2

DIFFERENT METHODS EXPLAINED BELOW:

Method-1 Using [] :

>>> a1 = []

i3

On assigning an empty list to a1, there is no effect on a2. a2 still refers to the same list object but a1 now refers to an empty list.

Method-2 Using del [:]

>>> del a1[:]

i4

This deletes all the contents of the list object which a1 was pointing to. a1 now points to an empty list. Since a2 was also referring to the same list object, it also becomes an empty list.

Method-3 Using del a1

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

i5

This deletes the variable a1 from the scope. Here, just the variable a1 is removed, the original list is still present in the memory. a2 still points to that original list which a1 used to point to. If we now try to access a1, we will get a NameError.

Answered By: Rahul Gupta
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.