Yuushi
Yuushi

Reputation: 26080

Garbage collector missing last value in list

While testing a class that holds weak references, I stumbled upon this slightly odd behavior: the Python garbage collector seems to be missing the last element in a list. A minimal example:

class Test(object):
    
    def __init__(self, i):
        self.i = i
        
    def __del__(self):
        print('Deleting Test {0}'.format(self.i))

if __name__ == '__main__':
        
    x = [Test(i) for i in range(5)]
    for t in x:
        print(t.i)
    x = []

The above will print:

0

1

2

3

4

Deleting Test 3

Deleting Test 2

Deleting Test 1

Deleting Test 0

This happens whatever the size of the list of created objects (10, 100, 1000, etc). To double check that this is the case, I've tried to force garbage collection and made sure that a weak reference to the original list value can still be used (and is not marked as dead) after setting the original list to [] or calling del x:

import weakref
import gc

z = None

if __name__ == '__main__':
    x = [Test(i) for i in range(5)]
    for t in x:
        print(t.i)

    z = weakref.ref(x[4])
    x = []
    gc.collect(2)
    print(z().i)

Further, trying to create a large list to (again) force garbage collection does nothing; for example, inserting the following between x = [] and gc.collect(2) above:

p = [i for i in range(10000000)]

This occurs on both Python 2.7.6 and 3.3.3. I realize garbage collection is non-deterministic, but this seems rather suspicious. Is there a specific reason the last element is not garbage collected, or is this some kind of off-by-one error?

Upvotes: 2

Views: 88

Answers (1)

Sebastian Stigler
Sebastian Stigler

Reputation: 7299

The variable t in your first sourcecode still exists and holds a reference to the last entry. After you call del t the last Test Object will be deleted.

Upvotes: 5

Related Questions