Weak References in Python

In Python, we never have to think about memory management because it is done automatically. The reference count is what is used in python for checking if garbage collection should be done or not. So, what happens behind the scenes is that the garbage collector frees the memory that is no longer needed which it finds out by looking the reference count. 

As everything in Python is an object so if an object is referenced by another object then it has a non-zero count and can’t be garbage collected (if not manually performed). 

Below is a short example on how can we find the reference count of any object in python.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

import ctypes
  
# list object which is referenced by
# my_list
my_list = [1, 2, 3]
  
# finding the id of list object
my_list_address = id(my_list)
  
# finds reference count of my_list
ref_count = ctypes.c_long.from_address(my_list_address).value
  
print(f"Reference count for my_list is: {ref_count}")

chevron_right


Output:

Reference count for my_list is: 1

So, now as we are clear with the basics of references and garbage collections let’s move to what are weak references and why do we need them?



What are Weak Reference?

Unlike the references we discussed above , a weak reference is a reference that does not protect the object from getting garbage collected. Why do we want such a thing in the first place?

There are two main applications of weak references:

  • Implement caches for large objects (weak dictionaries).
  • Reduction of Pain from circular references.

To create weak references, Python has provided us with a module named weakref. A point to keep in mind before using weakref is that some builtins such as tuple or int does not support this. list and dict support is either but we can add support through subclassing. Let’s discuss about the applications in detail.

Weakref module

Sometimes a large object is stored in the cache so there is no need to keep it alive. Let’s you have a large number of image objects and they are being used as keys to map to images due to which these objects will be kept alive. 

Fortunately, weakref module provides something called as WeakKeyDictionary and WeakValueDictionary don’t keep the objects alive as they appear in the mapping objects.

The following classes and methods are provided by weakref module:

  • class weakref.ref(object[, callback])  – This returns a weak reference to the object.
  • weakref.proxy(object[, callback]) – This returns a proxy to object which uses a weak reference.
  • weakref.getweakrefcount(object) – Return the number of weak references and proxies which refer to object.
  • weakref.getweakrefs(object) – Return a list of all weak reference and proxy objects which refer to object.

Let’s understand the working with some examples:

Example 1: 



In the below-given example we create normal list object, a weak reference list object, and a proxy list object and print the weak reference count for all of them.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# importing weakref module
import weakref
  
# creating a class
class GFG(list):
    pass
  
# creating object of a class
obj = GFG("Geeks")
  
# creating a normal list object
normal_list = obj
print(f"This is a normal object: {normal_list}")
  
# this returns a weak reference to obj
weak_list = weakref.ref(obj)
weak_list_obj = weak_list()
print(f"This is a object created using weak reference: {weak_list_obj}")
  
# creating a proxy of original object
proxy_list = weakref.proxy(obj)
print(f"This is a proxy object: {proxy_list}")
  
# printing the count of weak references
for objects in [normal_list, weak_list_obj, proxy_list]:
    print(f"Number of weak references: {weakref.getweakrefcount(objects)}")

chevron_right


Output:

This is a normal object: [‘G’, ‘e’, ‘e’, ‘k’, ‘s’]
This is a object created using weak reference: [‘G’, ‘e’, ‘e’, ‘k’, ‘s’]
This is a proxy object: [‘G’, ‘e’, ‘e’, ‘k’, ‘s’]
Number of weak references: 2
Number of weak references: 2
Number of weak references: 0

As the normal object has references to the weak reference object hence both of them have a weak reference count of 2 but as proxy_object is a proxy created from the weak reference thus it does not have a reference count.

Example 2:

In this example we will see how to use WeakValueDictionary which we discussed earlier in the article.

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# import weakref module
import weakref
  
# creates a class
class GFG:
  
    def __init__(self,data):
        self.data = data
      
    def __repr__(self):
        return str(self.data)
  
# creates an object of class GFG
# (consider that this object is very 
# large and has been stored in the cache)
value = GFG(5)
  
# creates a Weak Value Dictionary
weak_dict = weakref.WeakValueDictionary()
  
# inserting value into the dictionary
weak_dict["num"] = value
  
# getting the weak ref count
print(f'Weak reference count is: {weakref.getweakrefcount(weak_dict)}'
  
# deleting the weak dictionary
del weak_dict
  
# running this will generate error 
# print(weak_dict)

chevron_right


 
Output:

Weak reference count is: 1

In the above example we assumed that there is a really large object which has been placed in the cache so we have created a weak ref dictionary to store that key and value pair so it will be garbage collected.

 




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.