45

I create many object then I store in a list. But I want to delete them after some time because I create news one and don't want my memory goes high (in my case, it jumps to 20 gigs of ram if I don't delete it).

Here is a little code to illustrate what I trying to do:

class test:
    def __init__(self):
        self.a = "Hello World"
    def kill(self):
        del self

a = test()
b = test()
c = [a,b]

print("1)Before:",a,b)

for i in c:
    del i

for i in c:
    i.kill()   

print("2)After:",a,b)

A and B are my objects. C is a list of these two objects. I'm trying to delete it definitely with a for-loop in C: one time with DEL and other time with a function. It's not seem to work because the print continue to show the objects.

I need this because I create 100 000 objects many times. The first time I create 100k object, the second time another 100k but I don't need to keep the previous 100k. If I don't delete them, the memory usage goes really high, very quickly.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
Jean-Francois Gallant
  • 13,583
  • 6
  • 20
  • 24

4 Answers4

70

tl;dr;

mylist.clear()  # Added in Python 3.3
del mylist[:]

are probably the best ways to do this. The rest of this answer tries to explain why some of your other efforts didn't work.


cpython at least works on reference counting to determine when objects will be deleted. Here you have multiple references to the same objects. a refers to the same object that c[0] references. When you loop over c (for i in c:), at some point i also refers to that same object. the del keyword removes a single reference, so:

for i in c:
   del i

creates a reference to an object in c and then deletes that reference -- but the object still has other references (one stored in c for example) so it will persist.

In the same way:

def kill(self):
    del self

only deletes a reference to the object in that method. One way to remove all the references from a list is to use slice assignment:

mylist = list(range(10000))
mylist[:] = []
print(mylist)

Apparently you can also delete the slice to remove objects in place:

del mylist[:]  #This will implicitly call the `__delslice__` or `__delitem__` method.

This will remove all the references from mylist and also remove the references from anything that refers to mylist. Compared that to simply deleting the list -- e.g.

mylist = list(range(10000))
b = mylist
del mylist
#here we didn't get all the references to the objects we created ...
print(b) #[0, 1, 2, 3, 4, ...]

Finally, more recent python revisions have added a clear method which does the same thing that del mylist[:] does.

mylist = [1, 2, 3]
mylist.clear()
print(mylist)
mlibby
  • 162
  • 1
  • 8
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • @MartijnPieters -- You're right. Oh the magic of statements (as this wouldn't be possible with a function call -- `delete(mylist[:])`) – mgilson Jan 22 '13 at 18:23
  • 2
    soo , how I can delete A and B in a loop ? – Jean-Francois Gallant Jan 22 '13 at 18:24
  • 2
    @Jean-FrancoisGallant -- you can't. Not with the way your code is set up. To delete `a` and `b` in your code, you'd need: `del a; del b; del c[:]` -- That said, I doubt that your test code is actually a good model for what you're actually trying to do ... – mgilson Jan 22 '13 at 18:25
  • yes it's true. Soo I need to find a way to setup my code well. – Jean-Francois Gallant Jan 22 '13 at 18:28
  • @Jean-Francois Gallant: Just put the list inside a function and you're done – Jochen Ritzel Jan 22 '13 at 18:36
  • but why my memory never go down when I delete a very long list ? – Jean-Francois Gallant Jan 22 '13 at 18:39
  • @Jean-Francois Gallant: You never deleted anything in your code except aliases for your list and it's contents. – Jochen Ritzel Jan 22 '13 at 18:40
  • but if I do: mylist = list(range(1000000000...)) until I reach 2gigs of ram ... and I do del:mylist after that .... memory don't goes down. Why ? – Jean-Francois Gallant Jan 22 '13 at 18:51
  • 2
    @Jean-FrancoisGallant -- Python never actually states when memory gets returned to the OS for re-use. It only states when memory gets given back to python for re-use. So, there really aren't guarantees about memory going back to the OS (AFAIK). You might also want to try some of the functions in the [`gc` module](http://docs.python.org/2/library/gc.html). I'm specifically thinking of `gc.collect` before you examine your memory usage... That might help. – mgilson Jan 22 '13 at 18:57
  • yes it's working with gc.collect(). Well now , I check how I can delete all references to a object when it's done recursively. Like A.child = B , B.child = C .... etc – Jean-Francois Gallant Jan 22 '13 at 19:06
32

Here's how you delete every item from a list.

del c[:]

Here's how you delete the first two items from a list.

del c[:2]

Here's how you delete a single item from a list (a in your case), assuming c is a list.

del c[0]
Daniel777
  • 851
  • 8
  • 20
Jon-Eric
  • 16,977
  • 9
  • 65
  • 97
  • @ThiefMaster Ah, learned something new. It makes sense now that I think about it. Thanks! I'll update the answer. – Jon-Eric Jan 22 '13 at 18:21
  • 2
    @ThiefMaster: indeed, and is faster too. Python 3.3: `timeit.timeit('del alist[:]', 'alist = list(range(10000))')` vs. `timeit.timeit('alist[:] = []', 'alist = list(range(10000))')` comes out as 0.08622030797414482 and 0.1133101258892566 respectively. – Martijn Pieters Jan 22 '13 at 18:23
1

If the goal is to delete the objects a and b themselves (which appears to be the case), forming the list [a, b] is not helpful. Instead, one should keep a list of strings used as the names of those objects. These allow one to delete the objects in a loop, by accessing the globals() dictionary.

c = ['a', 'b']
# create and work with a and b    
for i in c:
    del globals()[i]
0

To delete all objects in a list, you can directly write list = []

Here is example:

>>> a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a = []
>>> a
[]
trojek
  • 3,078
  • 2
  • 29
  • 52
  • But why is this not the preferred way? Why most of the answers are of del var[:] ? – jeffry copps May 22 '18 at 06:01
  • 4
    @jeffrycopps Because this is an answer to a different question. `a = []` only changes `a` so that it now points to a new, empty list. It does not modify the original list, which may still have other references attached to it, and thus remain in memory. (In addition, this does not address the root issue of deleting several _objects_ from memory.) –  Jun 20 '18 at 09:40