-->

How to delete a function argument early?

2019-07-10 16:43发布

问题:

I'm writing a function which takes a huge argument, and runs for a long time. It needs the argument only halfway. Is there a way for the function to delete the value pointed to by the argument if there are no more references to it?

I was able to get it deleted as soon as the function returns, like this:

def f(m):
  print 'S1'
  m = None
  #__import__('gc').collect()  # Uncommenting this doesn't help.
  print 'S2'
class M(object):   
  def __del__(self):
    print '__del__'
f(M())

This prints:

S1
S2
__del__

I need:

S1
__del__
S2

I was also trying def f(*args): and def f(**kwargs), but it didn't help, I still get __del__ last.

Please note that my code is relying on the fact that Python has reference counting, and __del__ gets called as soon as an object's reference count drops to zero. I want the reference count of a function argument drop to zero in the middle of a function. Is this possible?

Please note that I know of a workaround: passing a list of arguments:

def f(ms):
  print 'S1'
  del ms[:]
  print 'S2'
class M(object):   
  def __del__(self):
    print '__del__'
f([M()])

This prints:

S1
__del__
S2

Is there a way to get the early deletion without changing the API (e.g. introducing lists to the arguments)?

If it's hard to get a portable solution which works in many Python implementations, I need something which works in the most recent CPython 2.7. It doesn't have to be documented.

回答1:

From the documentation:

CPython implementation detail: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references. See the documentation of the gc module for information on controlling the collection of cyclic garbage. Other implementations act differently and CPython may change. Do not depend on immediate finalization of objects when they become unreachable (ex: always close files).

Short of modifying the interpreter yourself, you cannot achieve what you want. __del__ will be called when the interpreter decides to do it.



回答2:

It look like it's not possible to do the early deletion in CPython 2.7 without changing the API of the f function.