💡 Advanced Python Concepts
Estimated reading: 4 minutes 194 views

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:

ComponentDescription
type (__class__)Points to the object’s class
refcountNumber 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

FunctionUse 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 classesAdding too many dynamic attributes
Use __dict__ and __class__ only for debuggingRelying on them in production logic
Use isinstance() for safe type checkingComparing types directly with ==
Understand id() and is for object identityConfuse 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__, and dir() 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 :
Share

Python Object Internals

Or Copy Link

CONTENTS
Scroll to Top