🔍 Python Object Internals – Understand How Python Objects Work Under the Hood
🧲 Introduction – Why Learn Python Object Internals?
Every value in Python—whether it’s an integer, string, function, or class—is an object. Understanding the internal structure of Python objects helps you:
- Write efficient and memory-safe code
- Understand attribute lookups and method resolution
- Debug complex issues in OOP, metaclasses, and descriptors
- Master Python at a deeper, more professional level
Whether you’re working on performance, design patterns, or frameworks—object internals are the foundation of Python programming.
🎯 In this guide, you’ll learn:
- What Python objects are made of
- How attributes are stored and accessed
- Special internal attributes (
__dict__
,__slots__
,__class__
) - Memory layout and object identity
- Inheritance and method resolution order (MRO)
✅ Everything Is an Object in Python
print(type(42)) # <class 'int'>
print(type("Hello")) # <class 'str'>
print(type(len)) # <class 'builtin_function_or_method'>
print(type(object)) # <class 'type'>
🧠 Even types and classes are themselves objects in Python. Python follows a consistent object model, with everything derived from object
.
🧱 Internal Structure of Python Objects
Each Python object has a fixed internal layout. At a high level, this includes:
Component | Description |
---|---|
type (__class__ ) | Points to the object’s class |
refcount | Number of references (used by garbage collector) |
__dict__ | A dictionary storing instance attributes |
__slots__ | Optional memory-saving layout for fixed attrs |
🔎 Using __dict__
to Inspect Attributes
class Person:
def __init__(self, name):
self.name = name
self.age = 30
p = Person("Alice")
print(p.__dict__)
✅ Output:
{'name': 'Alice', 'age': 30}
💡 All instance attributes are stored in the __dict__
unless __slots__
is defined.
💼 Optimize with __slots__
class User:
__slots__ = ('username', 'email')
def __init__(self, username, email):
self.username = username
self.email = email
✅ Benefits:
- Saves memory (no
__dict__
) - Slight speed improvement
- Prevents creation of new attributes
⚠️ __slots__
is optional and used in performance-critical code.
🧠 Understanding __class__
Every object has a reference to its class via __class__
:
x = 10
print(x.__class__) # <class 'int'>
🔁 Method Resolution Order (MRO)
MRO defines how Python looks up methods in case of inheritance.
✅ Example:
class A: pass
class B(A): pass
class C(B): pass
print(C.__mro__)
✅ Output:
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
💡 Python uses the C3 Linearization Algorithm for MRO.
🧬 Identity and Memory with id()
x = "hello"
print(id(x)) # Memory address of object
✅ id()
returns the unique identity of an object, used for object comparison.
🧠 Interning of Small Objects
Python caches small immutable objects for performance.
a = 100
b = 100
print(a is b) # ✅ True – same object (cached)
a = 1000
b = 1000
print(a is b) # ❌ Might be False – not interned
🧰 Built-in Tools to Inspect Objects
Function | Use Case |
---|---|
type(obj) | Get the object’s class |
dir(obj) | List all available attributes/methods |
hasattr(obj, x) | Check if object has an attribute |
getattr(obj, x) | Dynamically get an attribute value |
setattr(obj, x, v) | Dynamically set an attribute |
isinstance(obj, T) | Check if object is an instance of a class |
🧰 Real-World Use Case – Dynamic Object Introspection
def dump_object(obj):
print(f"Class: {obj.__class__.__name__}")
print("Attributes:", obj.__dict__)
print("Methods:", [m for m in dir(obj) if callable(getattr(obj, m)) and not m.startswith("__")])
class Product:
def __init__(self, name):
self.name = name
def display(self):
print("Product:", self.name)
p = Product("Laptop")
dump_object(p)
✅ Useful for debuggers, serializers, and frameworks.
📘 Best Practices
✅ Do This | ❌ Avoid This |
---|---|
Use __slots__ for performance-critical classes | Adding too many dynamic attributes |
Use __dict__ and __class__ only for debugging | Relying on them in production logic |
Use isinstance() for safe type checking | Comparing types directly with == |
Understand id() and is for object identity | Confuse with == (value comparison) |
📌 Summary – Recap & Next Steps
Python object internals give you deep insight into how objects store attributes, manage memory, and resolve methods.
🔍 Key Takeaways:
- ✅ All Python values are objects with class, attributes, and identity
- ✅ Instance variables live in
__dict__
- ✅ Use
__slots__
to reduce memory for fixed-attribute classes - ✅ MRO controls how methods are resolved in inheritance
- ✅
id()
,__class__
, anddir()
reveal internal structure
⚙️ Real-World Relevance:
Essential for writing frameworks, building ORMs, debugging tools, and performance optimization.
❓ FAQ – Python Object Internals
❓ What is __dict__
?
✅ A dictionary holding an object’s writable attributes.
❓ What is __slots__
used for?
✅ To restrict attribute creation and save memory by removing __dict__
.
❓ What’s the difference between is
and ==
?
is
: checks object identity==
: checks value equality
❓ How can I find an object’s class?
✅ Use obj.__class__
or type(obj)
.
❓ What is the MRO?
✅ MRO (Method Resolution Order) is the order Python uses to search for methods in a class hierarchy.
Share Now :