Maximus S
Maximus S

Reputation: 11095

Behavior of del operator in Python

I am wondering why the following doesn't work.

class Node(object):
    def __init__(self, data, next=None):
        self.data = data
        self.next = next

    def remove(self, value):
        if self is None:
            return False
        if self.data == value:
            if self.next:
                self.data = self.next.data
                self.next = self.next.next
            else:
                del self
        else:
            self.next.remove(value)

    node = Node(4)
    node.append(Node(3))
    node.remove(3)
    print node.next.data
    #prints 3

del doesn't delete the element from the linked list. I had to modify the delete() function so that I have a pointer to the parent of the target element.

class Node(object):
    def __init__(self, data, next=None):
        self.data = data
        self.next = next

    def remove(self, value):
        if self is None:
            return False
        if self.data == value:
            if self.next:
                self.data = self.next.data
                self.next = self.next.next
            else:
                del self
        else:
            current = self
            while current.next:
                if current.next.data == value:
                    if current.next.next:
                        current.next = current.next.next
                    else:
                        current.next = None

From the console,

node = Node(4)
current = node
del current #node is not deleted because I am only deleting the pointer
del node #node is deleted

This seems logical to me. However, I am not sure why the first code block doesn't work as I expect.

Upvotes: 2

Views: 1029

Answers (1)

Walle Cyril
Walle Cyril

Reputation: 3247

I ll explain why it doesn't work. But first you need to know that you rarely need to create linked lists in Python since the list type already offer you almost everything.

>>> [2*i for i in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> list_1=[2*i for i in range(10)]
>>> i=0
>>> list_1[i]#first
0
>>> i=i+1
>>> list_1[i]#next
2
>>> list_1[-1]#last
18
>>> len(list_1)#size
10
>>> del list_1[-1]# del the last
#delete all (list_1 becomes empty)
for i in range(len(list_1)):
    del list_1[0]

at the end loop we only delete the first n times but when you del the first in a list the other object go 1 place back.That way you can easily manipulate lists as if they were linked list and delete any elements without worrying about an empty slot. In addition to this, list have several very usefull methods like append, remove, sort, shuffle and more. Look at the docs https://docs.python.org/3.5/library/stdtypes.html?highlight=list#list

Now back to you question: Let s take a look to your remove method

if self is None:
    return False

this is useless, you can only call .remove with an object that has this method. None.remove() never works. If self is None it will throw an error before any (impossible) call.

else:
    del self

When you see self in an Object's method it is just a reference to the object itself, del sel will just delete the local reference. If you really want to destroy an object you must destroy it with del on every reference. Python will forget about your object if no living variable is looking at it. You can also overwrite the reference.

>>> node = Node(4)
>>> node = 3# the Node object is erased because you can t have access to it

Overall, I didn't really understand the goal of your Node class except to create linked lists, but as I said, you can do that with list(). In general you don't need to care about what is deleted or not in Python since Python will overwritte the memory if there is no reference left to an object.

Upvotes: 1

Related Questions