Search code examples
pythonstaticinstance

Why I can't delete (remove) the clearly 'existing instance' of the static list in Python?


My purpose is as below: If a new instance created, the instance must be added to the static list. and when a created instance is deleted, it must be deleted from the static list

And finalizer method, 'del()' must be used.

The python code I had trouble with is as below:

class Staff:
    staffs = []  # static customer list

    def __init__(self, name):
        self.name = name
        print("A staff is created!")

    def __del__(self):
        Staff.staffs.remove(self)
        print("A staff is deleted!")

if __name__ == '__main__':
    # create a staff
    Staff.staffs.append(Staff("Harry"))

    # delete a staff
    Staff.staffs[0].__del__()

And the error is as below:

Exception ignored in: <function Staff.del at 0x0000028A3675EF70>

Traceback (most recent call last): File "(Path)\temp.py", line 11, in del Staff.staffs.remove(self)

ValueError: list.remove(x): x not in list

And I can check that the created instance exists in the static list like below code

def check(self):
    print("Length of Static List:", len(Staff.staffs))
    print("self", self)
    for a_staff in Staff.staffs:
        if a_staff == self:
            print("a_staff", a_staff)
    print()

Result:

Length of Static List: 1

self <main.Staff object at 0x000001FF7506CFD0>

a_staff <main.Staff object at 0x000001FF7506CFD0>

The memory addresses of the instances are totally the same but I don't know why the interpreter says that there is no instance in the static list.

When I ran similar code in Java there was no problem.

Why does the error occur?


Solution

  • Note that

    class Staff:
        staffs = []  # static customer list
    
        def __init__(self, name):
            self.name = name
            print("A staff is created!")
    
        def delete(self):
            Staff.staffs.remove(self)
            print("A staff is deleted!")
    
    if __name__ == '__main__':
        # create a staff
        Staff.staffs.append(Staff("Harry"))
    
        # delete a staff
        Staff.staffs[0].delete()
    

    works fine. All I have done is renamed __del__ to delete. You can try to interpret the documentation on it which notes that

    Due to the precarious circumstances under which del() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead.

    The above quote explains your error. However, as other posts outline, __del__ is a

    really low-level method which you don't need 99.9% of the time

    so it should be sufficient to just use the code above, which marks your instance for garbage collection.

    If you must add additional content to the __del__ command, try this:

    class Staff:
        staffs = []  # static customer list
    
        def __init__(self, name):
            self.name = name
            print("A staff is created!")
    
        def __del__(self):
            print("A staff is deleted!")
    
    if __name__ == '__main__':
        # create a staff
        Staff.staffs.append(Staff("Harry"))
    
        print(f"The length of Staff before delete is: {len(Staff.staffs)}")
        # delete a staff
        del Staff.staffs[0]
        print(f"The length of Staff after delete is: {len(Staff.staffs)}")
    

    This outputs:

    A staff is created!
    The length of Staff before delete is: 1
    A staff is deleted!
    The length of Staff after delete is: 0

    So the item is deleted, and your text is printed, with no exception!