How is memory managed in Python?

Overview

Python is a high-level programming language implemented in the C programming language. The Python memory management system handles memory allocations in Python. Understanding memory management is crucial for a software developer. Because Python is so widely used in software development, building memory-efficient Python code is usually a need. As the use of massive data expands, the necessity of memory management is now stress-free.

Understanding Python memory management is an excellent start to building more efficient programs. Finally, we may make it a habit that we can apply to other programming languages with which we are familiar. In this Educative Answer, we’ll go over all there is to know about memory management in Python.

How memory is managed in Python

According to the Python memory management documentation, Python has a private heap that stores our program’s objects and data structures. Python memory manager takes care of the bulk of the memory management work and allows us to concentrate on our code.

Types of memory allocation

There are two types of memory allocation in Python, static and dynamic.

1. Static memory

The stack data structure provides static memory allocation, meaning the variables are in the stack memory. Statically assigned variables, as the name implies, are permanent; this means that they must be allocated in advance and persist for the duration of the program. Another point to remember is that we cannot reuse the memory allocated in the stack memory. Therefore, memory reusability is not possible.

x = 20
y = []
z = ""

2. Dynamic memory

The dynamic memory allocation uses heap data structures in its implementation, implying that variables are in the heap memory. As the name suggests, dynamically allocated variables are not permanent and can be changed while a program is running. Additionally, allotted memory can be relinquished and reused. However, it takes longer to complete because dynamic memory allocation occurs during program execution. Furthermore, after utilizing the allocated memory, we must release it. Otherwise, problems such as memory leaks might arise.

x = [0]*5 #This memory for 5 integers is allocated on heap.

Python garbage collection

The Python garbage collector handles memory allocation and deallocation automatically in Python. Python developers have designed it to eliminate the need for manual garbage collection. Garbage collection in Python refers to the interpreter’s memory management process of freeing up unneeded and undesired memory for our applications.

Note: Python uses garbage collection to release memory blocks no longer in use.

The garbage collector (GC) operates in the background and is triggered when the reference count reaches zero.

The reference count rises when the following occur:

  • An object is given a new name
  • An object is placed in a container, such as a tuple or a dictionary

The reference count lowers when the following occurs:

  • An object’s reference is reassigned
  • An object’s reference moves out of scope
  • An object is removed

The memory is a heap that stores the program’s objects and other data structures. The Python memory manager uses API methods to handle the allocation and deallocation of this heap space.

Let's see a basic example of how it works:

class Test(object):
pass
x = Test()
x.obj = x
del x

We create a new Class in the example above. After that, we created an instance of the class and made it a property of itself. Finally, we remove the instance from the system.  The instance is no longer available in our Python application when we delete it.

Let's see how to use the gc module in Python:

import gc
print(gc.get_threshold())

As we can see, we import the gc module and print the garbage collection thresholds. From the output, Python has a threshold of 700 for the youngest generation and 10 for each two older generations by default.

We may use the get_count() method to get the number of objects in each of our generations:

import gc
print(gc.get_count())

The gc.collect() method returns the number of collected and deallocated items.

import gc
print(gc.collect())

The set_threshold() method allows us to change the garbage collection thresholds.

import gc
gc.get_threshold()
gc.set_threshold(7777, 11, 11)
print(gc.get_threshold())

Conclusion

While Python takes care of most memory management for us, it’s still helpful to understand what’s going on under the curtain. We covered how memory is managed in Python in this Answer. We began by going over the fundamentals of memory management and the various forms of memory allocation. After that, we looked at how garbage collection works in Python, including the gc module.