plane
plane

Reputation: 23

Last object in a list isn't deleted after deleting it. When is it effectively deleted?

The following code should delete each of the n Human objects, then print the last line, but it deletes only 4 of them, the 5th gets deleted (I think) after execution stops.

class Human():
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f'{self.name} is dead')


n = 5
humans = []
for i in range(n):
    human = Human('Bob')
    humans.append(human)

for i in reversed(range(n)):
    del humans[i]

print('DEATH')

The output is the following (Powershell and Python 3.8.1):

Bob is dead  
Bob is dead  
Bob is dead  
Bob is dead  
DEATH  
Bob is dead

After the 2nd for-loop humans is empty, so it's not possible to delete the last item by del humans[0]. Other ways of deleting contents (del humans[:] or humans.clear) of the list also don't fix the issue, the output stays the same.

So, is this how the code should behave or is there some issue?

Upvotes: 2

Views: 220

Answers (1)

Samwise
Samwise

Reputation: 71522

One of the objects isn't being garbage-collected because there's still a reference to it:

class Human():
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f'{self.name} is dead')


n = 5
humans = []
for i in range(n):
    human = Human(f'Bob {i}')
    humans.append(human)

for i in reversed(range(n)):
    print(f'Die, {humans[i].name}!')
    del humans[i]

print('DEATH')
print(f"(except for {human.name} whom we haven't forgotten about!)")

If you want to avoid that dangling reference, an easy fix is not to create it in the first place:

n = 5
humans = []
for i in range(n):
    humans.append(Human(f'Bob {i}'))

or better yet:

n = 5
humans = [Human(f'Bob {i}') for i in range(n)]

Upvotes: 8

Related Questions