2

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.

smci
  • 32,567
  • 20
  • 113
  • 146
Maximus S
  • 10,759
  • 19
  • 75
  • 154
  • 1
    duplicate http://stackoverflow.com/questions/293431/python-object-deleting-itself – voscausa Nov 25 '13 at 02:20
  • 1
    check this out: http://stackoverflow.com/questions/293431/python-object-deleting-itself – zyy_max Nov 25 '13 at 02:20
  • It might be helpful to see the best solution for this specific problem. – Maximus S Nov 25 '13 at 02:22
  • 4
    Variables in Python are just names for things. `del` removes a name from an object; it doesn't mean "destroy the object". I recommend making a `List` class to manage nodes; if you store `Node`s directly, you won't be able to remove the thing in the first node without awkward workarounds. – user2357112 Nov 25 '13 at 02:47
  • Yes but creating a `List` class is just another workaround. I am still confused why the recursive function inside the class doesn't work, even with the understanding of garbage collection and references. – Maximus S Nov 25 '13 at 04:30
  • 1
    @user2357112 Please post that as an answer - or else we should just close this as duplicate. – smci Apr 11 '14 at 09:22
  • @MaximusS You don't need to check for "self" being None. What exactly do you think you're preventing with that check? – Zoran Pavlovic Jul 06 '14 at 22:23
  • Vote to remove to code-review stackexchange. – Zoran Pavlovic Jul 06 '14 at 22:23

1 Answers1

1

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.

Walle Cyril
  • 3,087
  • 4
  • 23
  • 55
  • `Node.remove(None, foo)` would work and result in `self is None` - but that's nothing you need to consider. – ThiefMaster May 25 '14 at 11:38
  • It would throw TypeError: remove() takes 2 positional arguments but 3 were given. Because methods make self what is before the -->.<-- – Walle Cyril May 25 '14 at 11:53
  • Wrong. When calling it on the class directly you have the unbound method which DOES accept an explicit `self`. However, I forgot that Python ensures you only pass instances of the containing class so None is rejected nonetheless (no pun intended). https://gist.github.com/ThiefMaster/3c101347fd6267b5ca09 – ThiefMaster May 25 '14 at 13:34