__sizeof__
__sizeof__(self) int · Added in v3.0 · Updated April 1, 2026 · Dunder Methods __sizeof__ returns the size of an object in bytes, as allocated by the Python interpreter. It measures only the object’s own memory footprint, not the total size of everything the object references.
Every Python object inherits __sizeof__ from object, so it’s available on all types — built-in and custom alike. Override it in your own classes to provide a meaningful size report.
Basic Usage
Call __sizeof__ on any object:
# Empty containers show base overhead
[].__sizeof__() # 40
{}.__sizeof__() # 216
"".__sizeof__() # 49
# Sizes grow with content
[1, 2, 3].__sizeof__() # 64
"hello".__sizeof__() # 54
{"a": 1}.__sizeof__() # 216
For lists and tuples, each element pointer costs 8 bytes on a 64-bit interpreter. Strings include their character data in the object itself.
__sizeof__ vs sys.getsizeof()
These two get confused, but they’re different:
__sizeof__() | sys.getsizeof() | |
|---|---|---|
| What it measures | Object’s raw size | Object size + GC bookkeeping |
| Type | Method on object | Function in sys module |
| GC overhead | Not included | Included for tracked objects |
import sys
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Alice', 30)
print(p.__sizeof__()) # 32 — object's own size
print(sys.getsizeof(p)) # 56 — adds GC overhead
The 24-byte gap is the garbage collector’s header overhead. sys.getsizeof always calls __sizeof__ first, then adds extra bytes for objects the GC tracks.
Note that sys.getsizeof does not add GC overhead for all types. For simple types like int, it calls __sizeof__ directly with nothing added.
Custom Class Implementation
Override __sizeof__ to report your object’s actual memory footprint. Call object.__sizeof__(self) to get the base instance size:
class Point:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
def __sizeof__(self):
return object.__sizeof__(self)
p = Point(1, 2)
print(p.__sizeof__()) # Smaller than a class with __dict__
Without __slots__, the instance will also have a __dict__. If you override __sizeof__ and don’t account for it, you’ll underreport the actual size:
import sys
class BadPoint:
def __init__(self, x, y):
self.x = x
self.y = y
def __sizeof__(self):
return object.__sizeof__(self) # Missing __dict__!
class GoodPoint:
def __init__(self, x, y):
self.x = x
self.y = y
def __sizeof__(self):
return object.__sizeof__(self) + sys.getsizeof(self.__dict__)
bp = BadPoint(1, 2)
gp = GoodPoint(1, 2)
print(bp.__sizeof__()) # Undercounts
print(gp.__sizeof__()) # Accurate
Gotchas
Sizes differ between Python implementations. CPython, PyPy, and Jython have different memory layouts. Compare sizes only within the same interpreter.
__sizeof__ is shallow. It measures only the object itself. A list reports its own size, not the combined size of every element inside it. Use sys.getsizeof recursively if you need a deep picture.
Dict sizes don’t grow linearly. An empty dict and a dict with one key often report the same size because dicts grow in bucket-based chunks, not by one entry at a time.
# Dict grows in jumps, not linearly
{}.__sizeof__() # 216
{"a": 1}.__sizeof__() # 216 — same bucket size
{"a": 1, "b": 2}.__sizeof__() # 216 — still same
See Also
sys.getsizeof()— measure object size including GC overhead__slots__— reduce instance size by eliminating__dict__