A Guide to Reference Counting in Python

In this piece, I will talk about reference counting in Python. I will use the list object, which is mutable for illustration purposes. I hope you will enjoy it. Note that I will not go into C implementation details.

P.S: Output of snippets may differ on your hardware.

Variables Are Memory References

Variables in Python are memory references. What happens when you say x=[1, 2] ? [1, 2] is the object. Recall that everything is an object in Python. [1, 2] will be created in memory. x is the memory reference of [1, 2] object.

Focus on the example below — you can find the memory address which x references to. Note that you can just use id(x) which will give you in base-10 and hex function converts it to hexadecimal.

Reference Counting

So far, we’ve created a list object in memory and x references to that object. What is the difference between y=[1,2] and y=x ?

When you say y=[1,2] it will create a new list object in memory and y will reference that.

Whereas when you say y=x , you basically tell Python that you want y variable to reference what x variable references to. Because variables are memory references.

You can confirm that x and y reference the same object.

The Number of Reference Counting

So far so good — we’ve learned a lot. Now, how many variables are referencing the one object?

The wrong use

I see some people using sys.getrefcount(var) without knowing passing the var add one more reference to the object. Let’s look at the example below.

Check that out! Output 3 while we expect 2 ( x and y ). It happens because passing x to getrefcount function added one more reference.

Better use

You can use the built-in ctypes module to find the result you expect. You have to pass id of x to from_address function.

Why does it happen this way? Because in the wrong use, you pass the variable whereas in the better use, you pass the id of variable, which means you only pass a number in base-10, not a variable.

When the Object Is Gone

What happens when no variable reference to an object? The object will be deleted from memory because nothing is referencing that object. Please note that there is an exception here. If there is a circular reference, garbage collector will come to play. I will not go into the garbage collector here.

Why I Used a Mutable Object

For immutable objects, the result might differ than you expect for performance reasons. I might discuss what is going behind the science in the future.

Check that example below and see how the outputs change.

Conclusion

Everything we’ve talked so far is valid for CPython. I hope you enjoy it.