Python Memory management
Published: 2022-04-24 17:00:14

## Introduction 
Memory is simply a space for storing data in computers. We can also think of memory as book, if we need to write something we must open a page with some space enough for holding the characters we are going to write. This process of writing to a page with enough space to hold our writing can be equally be figured out as **memory allocation** – providing space to hold a particular data in computer.

###Memory allocation
We have two kinds of memory allocation.

**1. Static memory allocation**
This technique is used in languages like C and C++, the static keyword is used during allocation of memory space. When we allocate static memory to data it means the memory cannot be reused ever in the program. Static memory is allocated during compilation of the program.
`Static int a=10;`
In python, to achieve static memory allocation we implement a stack data structure. Here a function is defined with variables temporarily defined to it. Then the stack function returns the. The function call returns the value and the stack proceeds to the next task.

**2. Dynamic memory allocation**
Here the Heap is implemented; memory allocations happens during runtime of the program. In C and C++ `int a, char str[20]` leads to automatic allocation and deallocation of memory spaces since we have a predefined size of the data but no length size information. For dynamic memory allocation the memory space can be used throughout the program.
Heap memory allocation means the memory can be freed up if not in use or when the contents of the memory have been deleted.

### Implementation of memory management in python
**Cpython**
The default implementation of memory management in python is through CPython – a library which is written in C programing language. Python is interpreted and compiled down into bytecodes which are computer readable codes. For more information about Cpython refer to the following  [documentation](https://docs.python.org/3/c-api/index.html )
**Garbage collector**
The free memory is freed up in python. The GC module in python is used to carry out the object tracking. GC has three generations; first, second and third. A new object starts life at first generation when the python interpreter performs garbage collection and the object survives it moves to the second older generation and so on. For each generation, the garbage collector module has a threshold number of objects. If the number of objects exceeds that threshold, the garbage collector will trigger a collection process. For any objects that survive that process, they’re moved into an older generation.

```
Import gc
gc.get_threshold()
#outputs (700,10,10)
```
700 is the first generation, 10 the second generation and the other 10 refers to the third generation.
Running a garbage collection process cleans up a huge amount of objects. 
The `gc.get_count()` method is used to check number of generations in each count.
More information about garbage collector can be found in the [following website](https://stackify.com/python-garbage-collection/ )

## #Ways to reduce space complexity

- Avoid list slicing
list slicing creates a copy of the object

- Use list indexing carefully
Instead of using `for index in range(len(array))` use `for item in array`.

- Avoid too much use of “+” operator in string concatenation 
instead try:

```
a=”millet”
a=a+” ugali”
print(a) #output millet ugali
```
instead of 

```
a=”millet” +” ugali”
```

## References

1. [javapoint](https://www.javatpoint.com/python-memory-management)
2. [stackify](https://stackify.com/python-garbage-collection/)
3. [Cpython](https://docs.python.org/3/c-api/index.html )
4. [Memory management](https://docs.python.org/3/c-api/memory.html)