Python __sizeof__ Method
Last modified April 8, 2025
This comprehensive guide explores Python's __sizeof__
method, the
special method that returns the memory consumption of an object. We'll cover
basic usage, built-in types, custom objects, and practical examples.
Basic Definitions
The __sizeof__
method returns the size of an object in bytes, as
allocated by the interpreter. It provides insight into memory usage and helps
with optimization.
Key characteristics: it's automatically called by sys.getsizeof()
,
returns an integer, and can be overridden in custom classes. The size includes
the object's overhead but not referenced objects.
Basic __sizeof__ Usage
Here's how to use __sizeof__
with built-in types to measure their
memory consumption. This demonstrates the method's basic behavior.
import sys lst = [1, 2, 3, 4, 5] print(lst.__sizeof__()) # Direct method call print(sys.getsizeof(lst)) # Recommended way using sys empty_list = [] print(empty_list.__sizeof__()) s = "hello" print(s.__sizeof__())
This example shows memory usage for a list and string. The empty list still has
overhead from Python's list structure. sys.getsizeof()
is preferred
as it handles edge cases.
Note that sizes may vary between Python versions and implementations (CPython, PyPy). The values represent memory at the Python level, not necessarily the system level.
Custom Class with __sizeof__
Implementing __sizeof__
in custom classes allows measuring their
memory footprint. This example shows a simple implementation.
import sys class Point: def __init__(self, x, y): self.x = x self.y = y def __sizeof__(self): return object.__sizeof__(self) + \ self.x.__sizeof__() + \ self.y.__sizeof__() p = Point(3, 4) print(sys.getsizeof(p))
This Point
The implementation sums the sizes of all components. For complex objects, you'd need to recursively calculate sizes of all referenced objects if needed.
Container Class with __sizeof__
For container objects, __sizeof__
should account for both the
container and its elements. This example demonstrates this pattern.
import sys class CustomList: def __init__(self, *args): self.data = list(args) def __sizeof__(self): size = object.__sizeof__(self) size += self.data.__sizeof__() for item in self.data: size += sys.getsizeof(item) return size cl = CustomList(1, "two", 3.0) print(sys.getsizeof(cl))
This CustomList
calculates its total size by summing the container
overhead, the internal list size, and each element's size. This provides a
complete memory picture.
For accurate measurements, we use sys.getsizeof()
on each element.
This accounts for Python's object overhead on each contained item.
__sizeof__ with Slots
Classes using __slots__
have different memory characteristics.
This example shows how to implement __sizeof__
for such classes.
import sys class SlotPoint: __slots__ = ['x', 'y'] def __init__(self, x, y): self.x = x self.y = y def __sizeof__(self): return object.__sizeof__(self) + \ sys.getsizeof(self.x) + \ sys.getsizeof(self.y) sp = SlotPoint(3, 4) print(sys.getsizeof(sp))
The SlotPoint
class uses __slots__
for memory
efficiency. Its __sizeof__
implementation is similar to regular
classes but with different base overhead.
Slots-based classes typically consume less memory than regular classes as they
don't have a __dict__
for dynamic attributes. This affects the
size calculation.
Recursive __sizeof__ Implementation
For complex nested structures, a recursive __sizeof__
implementation
can calculate total memory usage including referenced objects.
import sys class TreeNode: def __init__(self, value, left=None, right=None): self.value = value self.left = left self.right = right def __sizeof__(self): size = object.__sizeof__(self) size += sys.getsizeof(self.value) if self.left: size += sys.getsizeof(self.left) if self.right: size += sys.getsizeof(self.right) return size left = TreeNode(1) right = TreeNode(3) root = TreeNode(2, left, right) print(sys.getsizeof(root))
This TreeNode
class represents a binary tree. Its __sizeof__
method recursively includes the sizes of child nodes in its calculation.
For very deep structures, this approach might be inefficient. In such cases, consider iterative approaches or memoization to optimize the calculation.
Best Practices
- Use sys.getsizeof(): Prefer it over direct __sizeof__ calls
- Include all attributes: Account for all object components
- Handle recursion carefully: Avoid infinite loops with circular references
- Document assumptions: Clarify what's included in the size
- Compare with alternatives: Use for optimization decisions
Source References
Author
List all Python tutorials.