-1

I want to know exactly about Python del reserved words. In the process of studying linked list, I got curious about del reserved words. First, common frame code.

class Node:
    def __init__(self, data, nxt=None):
        self.data = data
        self.nxt = nxt
        
class NodeMgmt:
    def __init__(self, data):
        self.head = Node(data)
        
    def add(self, data):
        current_node = self.head
        while current_node.nxt is not None:
            current_node = current_node.nxt
        current_node.nxt = Node(data)
        
    def desc(self):
        current_node = self.head
        while current_node:
            print(current_node.data)
            current_node = current_node.nxt

I don't understand the result value of this code

    def delete(self,data):
        current_node = self.head          
        while current_node.data != data:
            current_node = current_node.nxt
        del current_node
lnk = NodeMgmt(1)
lnk.add(2)
lnk.desc() >>> 1 2
lnk.delete(2)
lnk.desc() >>> 1 2

I know the following code is correct.

   def delete(self,data):
        current_node = self.head
        current_node_parent = self.head
        while current_node:
            if current_node.data != data: 
                current_node_parent = current_node
                current_node = current_node.nxt
            else:
                break
                
        current_node_parent.nxt = current_node.nxt

I would like to point out clearly for the flexible use of del

li = [1,2,3]
li1 = li
li1.append(1)
print(li)
del li1[2:] 
print(li) # >>> [1,2]
del li1
print(li) # >>> [1,2] Why isn't this deleted?
Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31
  • 1
    Because you didn't `del li`? – mkrieger1 Sep 20 '22 at 10:18
  • There is no such thing as "del reserved words" in Python. – user2357112 Sep 20 '22 at 10:20
  • This would be a duplicate of https://stackoverflow.com/questions/73785112/i-want-to-know-exactly-about-python-del-reserved-words, if the first comment were an accepted answer. – mkrieger1 Sep 20 '22 at 10:20
  • Further to @mkrieger1, why should you expect `li` to be deleted? – Julien Sep 20 '22 at 10:22
  • 2
    @mkrieger1 I think you got that link wrong; right now it points back to this question! – Ture Pålsson Sep 20 '22 at 10:40
  • In the last example, we know that the list data type is a mutable data type. So li1 and li are looking at the same address. So even if you change li1, li will change. So I think li should be deleted if I do del li1, but I wonder why it will not be deleted. – KimGyeongMin-KR Sep 20 '22 at 10:46
  • You delete the name `li1`, not the data. The data might be freed automaically if you remove the last reference to it, but in this case it's still bound to `li`. To cite the documentation of [`del`](https://docs.python.org/3/reference/simple_stmts.html?highlight=del#grammar-token-python-grammar-del_stmt): "Deletion of a name removes the binding of that name from the local or global namespace, [...]" – Matthias Sep 20 '22 at 11:02
  • @TurePålsson Oops, thanks for noticing! I meant https://stackoverflow.com/questions/54894279/how-do-you-delete-a-pointed-to-value-is-that-possible – mkrieger1 Sep 20 '22 at 11:57

1 Answers1

0

Here we first describe the useage of the del statement to answer the title:

  1. When directly acting on a variable name (del some_object), it will delete the binding between the variable name and the object:
>>> foo = 1
>>> globals()
{'__name__': '__main__',
 '__doc__': None,
 '__package__': None,
 '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000025FF6957C40>,
 '__spec__': None,
 '__annotations__': {},
 '__builtins__': <module 'builtins' (built-in)>,
 'foo': 1}
>>> del foo
>>> globals()
{'__name__': '__main__',
 '__doc__': None,
 '__package__': None,
 '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000025FF6957C40>,
 '__spec__': None,
 '__annotations__': {},
 '__builtins__': <module 'builtins' (built-in)>}

There is no direct relationship with garbage collection here. It just deletes the key value pair with foo as the key from the namespace, and decreases the reference count of the object bound before foo by one. When the reference count of an object decreases to 0, it will be collected as garbage.

  1. When used for subscript (del some_object[subscript]), it delegates the deletion behavior to the object's __delitem__ method:
>>> class Foo:
...    def __delitem__(self, item):
...        print('deleting', item)
...
>>> foo = Foo()
>>> del foo[0]
deleting 0
>>> del foo[:]
deleting slice(None, None, None)
  1. When used for attribute (del some_object.attribute), it delegates the deletion behavior to the object's __delattr__ method:
>>> class Foo:
...     def __delattr__(self, item):
...         print('deleting', item)
...
>>> foo = Foo()
>>> del foo.attr
deleting attr
>>> del foo.foo
deleting foo

Next is the answer to the question in the description:

I don't understand the result value of this code

    def delete(self,data):
        current_node = self.head          
        while current_node.data != data:
            current_node = current_node.nxt
        del current_node
lnk = NodeMgmt(1)
lnk.add(2)
lnk.desc() >>> 1 2
lnk.delete(2)
lnk.desc() >>> 1 2

What you do here is: iterate the linked list, find the target node and bind the current_node to it, finally unbind the current_node to it. The whole process will not affect the linked list and target node, only the namespace. (and even if the del statement can successfully reclaim the node, the linked list will be disconnected from the middle.)

I would like to point out clearly for the flexible use of del

li = [1,2,3]
li1 = li
li1.append(1)
print(li)
del li1[2:] 
print(li) # >>> [1,2]
del li1
print(li) # >>> [1,2] Why isn't this deleted?

This involves the use of two different del statements:

  • del li1[2:] delegates the deletion to the list itself. Python's implementation is to delete the elements in the list within the slice range.
  • del li1 only unbinds li1 from the list, because li still binds the list, it will not be collected as garbage. Only when you also unbind the list from li will the list be collected. At the same time, because there is no longer a variable name bound to it, you cannot access the list that has been collected.
Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31