Python Memory Management
Python handles memory using reference counting, garbage collection, and memory pools
(PyMalloc).
Key Concepts:
- Reference Counting: Every object has a count of references. If it drops to 0, the memory is
released.
- Garbage Collection (GC): Handles cyclic references that reference counting can't.
- PyMalloc: Optimized memory allocator for small objects.
- Stack vs Heap: Stack is for call frames and locals; heap is for dynamic memory (e.g., objects).
Best Practices:
- Use generators to save memory
- Break circular references
- Use 'del' to remove unnecessary references
Generators in Python
Generators allow lazy evaluation using the 'yield' keyword.
Types:
- Generator Function: Uses 'yield' to produce values one at a time.
- Generator Expression: Like list comprehensions but uses parentheses.
Features:
- Lazy evaluation (values produced on the fly)
- Efficient memory usage
- Maintains state between yields
Example:
def my_gen():
yield 1
yield 2
yield 3
Used with: for val in my_gen(): print(val)
Iterators in Python
Iterators are objects with __iter__() and __next__() methods.
Example:
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current > self.end:
raise StopIteration
val = self.current
self.current += 1
return val
Difference between Iterable and Iterator:
- Iterable has __iter__()
- Iterator has __iter__() and __next__()
Generators vs Iterators:
- Generators use 'yield', have less boilerplate
- Iterators use class-based syntax, more control