In the last part, we checked out how variables are stored in Python and how Python handles memory management with reference counts and garbage collector. If you haven't checked it out and want to here is the link.
In this part, we will dig deep a little on how reference counting works and how it can increase or decrease taking in account the different cases. So let's start where we left off, every object in python has three things
Type Reference Count Value
Reference Count is a value showing how much an object has been referred(pointed) too by other names(variables). Reference counting helps the garbage collector in freeing up space so the program can run efficiently. Though we can increase or decrease the value of the reference count and can check the value with the inbuilt function called getrefcount().
Let's take a small code snippet:
import sys a =  # Two reference one from the variable and one from the getrefcount() function print(sys.getrefcount()) 2
Though the examples look great and everything seems to be working but I did kinda trick you, first thing is that not all reference count values start from 0 so if you do the same example with a different value of the output may be different. Reference count values are calculated on two factors number of times the object is used in the bytecode and the number of time it’s been referenced to this includes your previous programs too.
Let’s look into another example:
import sys a = 100 print(sys.getrefcount(a)) 4 b = 100 print(sys.getrefcount(b)) 5 c = 100 print(sys.getrefcount(c)) 6
When more variables reference to the same value the reference count increase. But this is not the case when we take into example the case of container objects like lists and constants.
import sys ex_list = [a,b,c,d] print(sys.getrefcount(a)) 8 print(sys.getrefcount(b)) 9 print(sys.getrefcount(c)) 10 print(sys.getrefcount(d)) 11 del ex_list print(sys.getrefcount(a)) 7 print(sys.getrefcount(b)) 8 print(sys.getrefcount(c)) 9 print(sys.getrefcount(d)) 10 # Same thing goes with constants print(sys.getrefcount(10)) 12 const = 10 print(sys.getrefcount(10)) 13 const = const + 10 print(sys.getrefcount(10)) 12
As we saw container objects here list refer to other objects referring to the value thus when we delete them the reference link is deleted thus objects inside the list decrease the reference count by one. The same happens with constants too, when the variable they get referenced to is incremented the reference count is decremented.
By now you must have realized that del does not actually delete the object on the contrary it removes that variable(name) as a reference to that object and decrease the reference count by one.
All the example we saw are kinda similar considering the fact that they are in the global namespace but what happens when there is function what happens to the reference count then, let’s find out through this code snippet.
import sys num = 100 print(sys.getrefcount(num)) 4 def ytf(number): print(sys.getrefcount(num)) ytf(num) 6 print(sys.getrefcount(num)) 4
We saw that when ytf() got into scope the reference count increased while the reference count decreased when the function got out of scope. Keeping this in mind that we should be careful of using large or complex objects in the global namespace because an object in a global namespace don’t go out of scope unless we decrease the value of the reference count thus a large object would consume more memory making the program less efficient.
That’s all for this part, in the next part we would look closely into the garbage collector and how it functions inside a python program in freeing up memory.