In a context manager what you would like to achieve is possible by returning a weak reference to the instance of Things
that does not increase the reference count of the object, and hence becomes an invalid reference once we __exit__
and the last reference of the object is not used anymore.
Then you don't have to call delete
manually after exiting the context manager.
In general this can be done simply by wrapping the return value of the __enter__
function:
import weakref
class Things(object):
...
def __enter__(self):
return weakref.proxy(self)
Your entire code snipplet looks as follows:
import weakref
class Things(object):
def __init__(self, clothes, food, money):
self.clothes = clothes
self.food = food
self.money = money
def __enter__(self):
return weakref.proxy(self)
def __exit__(self, exc_type, exc_val, exc_tb):
print('object deleted')
with Things('socks','food',12) as stuff:
greg = stuff.clothes
print(greg)
try:
print(stuff.clothes)
except ReferenceError as e:
print('Could not access stuff', e)
try:
print(stuff)
except ReferenceError as e:
print('Could not access stuff', e)
print(stuff is None, type(stuff))
The output of the program is
socks
object deleted
Could not access stuff weakly-referenced object no longer exists
Could not access stuff weakly-referenced object no longer exists
False <class 'weakproxy'>
As you see in the program's output, the only caveat of this solution is, that the Exception thrown when trying to access the variable stuff
is different from the Exception that would be thrown if the object were deleted, and that stuff
is of type weakproxy. But for all intents and purposes this solution does what it is supposed to do: raise an Exception when we try to access an object that is not supposed to be accessed anymore.
This solution works for both python2.7 and python3.x.
with
statement but continues to exist until the end of the script, as you observed. If you have a linedel stuff
then the name "stuff" becomes undefined. It is rare that you have to do this. – Bureaucratize