In this exercise, an instance is created and assigned to the variable facade_1. What happens to the instance if the variable is assigned to another object?
Answer
Python (like many other languages) will detect that an object is no longer being used and perform what is called “garbage collection”. During the process, unused objects are released to free up resources. When a variable is assigned to an instance and then assigned to a different instance, the prior assignment will be a candidate for “garbage collection” provided that no other variable is pointing to it. The following code example shows that the instance originally assigned to my_obj is destroyed when the variable is assigned to a new instance.
class TestClass:
def __init__(self, id):
self.id = id
print("Creating object id = " + str(self.id))
def __del__(self):
print("Deleting object id = " + str(self.id))
print("Instantiating object 1")
my_obj = TestClass(1)
print("Instantiating object 2")
my_obj2 = TestClass(2)
print("Instantiating object 3")
my_obj = TestClass(3)
# Wait for 10 seconds to show that object 1 is destroyed before the program ends
from time import sleep
sleep(10)
In the above example we see that object 1 is destroyed before our program ends.
Is it always correct to say that: everything is garbage collected after our code is run?
Depends on what you mean by garbage collection.
When your process exits all the memory of the program is reclaimed by the os, but that doesn’t necessarily mean that the program ran garbage collection.
If you care about memory being reclaimed then exiting the process will do that no matter what.
If you care about events happening when a value is forgotten (external resources, flushing buffers, files, etc) then you’d need to think long and hard about whether this would be done correctly by garbage collection.
The values in that example would all get caught by reference counting (not directly triggered by the program exiting, so the exiting is kind of irrelevant), this doesn’t happen when there are cyclical references, not sure whether python as a language promises to clean those up, or if cpython promises that. There’s also a module atexit for making things happen on exit. You also have to keep in mind that if your program exits abnormally (killed or crashed) then your program doesn’t get the chance to clean anything up.
I mean if it promises to garbage collect cyclical references before exiting, and if it does, whether that’s in the language spec or just cpython.
Also no clue how exceptions are dealt with during gc for cyclical objects.
Mainly my point is that if relying on events to be triggered by gc … that might not be the easiest thing to get right. No clue though.
The function of “self” is used to represent the instance of the class. For constructors, like the one in the class above, self has to be the first argument. However, it doesn’t have to be “self”. You can choose what you want to represent the instance of the class. I hope my response cleared your doubts.
I’m talking about this code sequence, given as an example in the question response by ajaxninja66418:
class TestClass:
def __init__(self, id):
self.id = id
print("Creating object id = " + str(self.id))
def __del__(self):
print("Deleting object id = " + str(self.id))
print("Instantiating object 1")
my_obj = TestClass(1)
print("Instantiating object 2")
my_obj2 = TestClass(2)
print("Instantiating object 3")
my_obj = TestClass(3)
# Wait for 10 seconds to show that object 1 is destroyed before the program ends
from time import sleep
sleep(10)
My output is:
Instantiating object 1
Creating object id = 1
Instantiating object 2
Creating object id = 2
Instantiating object 3
Creating object id = 3
Deleting object id = 1
Deleting object id = 2
Deleting object id = 3
I don’t understand what it’s doing and how the object appears destroyed.
The first bit is an example is the basic reference counting that python uses for objects.
my_obj = TestClass(1) # create a new object, assign to name
my_obj = TestClass(3) # we use the same name but assign a new object
# there are no references to first object created, it can be removed
Out: Deleting object id = 1
The second bit was, I assume, included to show the difference; that these objects still exist whereas the first one can be cleared.
In this case it also shows that these objects were garbage collected before the program finally terminated. As the link and previous messages mention being collected is not guaranteed for every object prior to the interpreter exiting.