2

I have the following code where I reassign a list of several GBs:

    res = self.dict_cursor.fetchall()
    res_with_offers = []

    # we add in HDBUY, SDBUY for now -- HARDCODED
    for item in res:
        for avail_code in ['HDBUY', 'SDBUY']:
            _item = deepcopy(item)
            _item['avail_code'] = avail_code
            res_with_offers.append(_item)

    del res; # <== is this line needed?
    res = res_with_offers

My understanding is that the del res;, as the variable reassignment on the line below it would delete the initial res item in memory. Is this correct? Why or why not?

David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    As an aside, languages with structural sharing support might be much more appropriate to tackle your problem while keeping memory use constrained -- in Clojure, f/e, you don't need `deepcopy()`, because native types/structures aren't mutable in the first place (and creating a new list/dict with a change doesn't change anything but the parents of the point in the tree where the change was made, reducing the amount of content that actually needs to be duplicated). – Charles Duffy Nov 18 '18 at 23:13

1 Answers1

5

An identifier may be bound to an object in Python, or it may not be bound to anything. That's all.

If identifier is bound to an object, del identifier removes the binding, leaving identifier not bound to anything. And that's all. It has no direct effect on whether memory is released.

When the last binding to an object is removed, the object becomes eligible for garbage collection. Not before then.

In the code you showed, it's actually not possible to determine when the object initially bound to res becomes eligible for garbage collection. For all we know, e.g., in

res = self.dict_cursor.fetchall()

the fetchall() returned an object from an internal persistent cache. Then

del res

would remove the binding to the object via res, but would have no effect on any other possible bindings to the object. The object can't be reclaimed until all bindings are gone.

In any case, the del res in:

del res
res = anything

serves no real purpose. res ends up being bound to anything regardless of whether del res is present, and so the original binding of res is removed too regardless of whether del res is present.

Tim Peters
  • 67,464
  • 13
  • 126
  • 132
  • Well, there might be a _little_ difference in memory overflow situations: When there is no `del` done, then for a moment the old value will be still alive and not collectible, while the new value is assigned. If a del is done before, Python might use `gc`and survive instead of memory overflow. – Christian Tismer Apr 21 '19 at 15:06