Python
Inheritance
Object-Oriented Programming
Classes
Programming Concepts

Why do Python classes inherit object?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

In the realm of Python programming, understanding why classes inherit from object is crucial for building efficient and modern Python applications. This article delves into the rationale and technical details of this inheritance, focusing on the distinctions between classic and new-style classes in Python, the advantages of inheriting from object, and some key points to consider when designing your Python classes.

A Historical Overview: Classic vs. New-Style Classes

To grasp why Python classes inherit object, it is helpful to understand the evolution of classes in Python.

Classic Classes

Before Python 2.2, all classes were considered "classic" or "old-style." These classes did not inherit from any base class implicitly or explicitly, and they represented objects using a simple mechanism similar to C structs. Classic classes had limitations, including:

  • Lack of a unified object model.
  • Some advanced features such as descriptors, properties, and super calls were not supported.

Introduction of New-Style Classes

With the introduction of Python 2.2, a new model was presented in the form of "new-style classes." A key feature of these classes is that they explicitly inherit from the object class or any subclass of it. This change aimed to unify types and classes, offering:

  • A consistent object model by having a common ancestor in the form of object.
  • Enhanced capabilities such as descriptors, magic methods, and better support for multiple inheritance.

Key Features of New-Style Classes

The adoption of object as a base class brought several benefits:

  1. Unified Type System: In new-style classes, everything derives from object, making functions such as isinstance() and issubclass() more reliable and efficient.
  2. Rich API: New-style classes offer a variety of methods and attributes absent in classic classes, such as __slots__, __getattribute__, and __mro__.
  3. Descriptor Protocol: This includes properties and static/class methods, facilitating more Pythonic code designs.
  4. Cooperative Multiple Inheritance: The C3 method resolution order (MRO) allows for a more predictable and well-structured hierarchy.

Technical Explanation: Why Inherit from object?

Any class defined in Python 3, other than built-in classes, is implicitly a new-style class because Python 3 does not support classic classes. However, in Python 2.x, a programmer must explicitly inherit from object to leverage the new-style class features. Here is why inheriting from object is advised:

Example: Utilizing super()

The super() function is a potent tool enabled by new-style classes that allows a programmer to call methods up the class hierarchy without hardcoding the parent class name:

python
1class A(object):
2    def greet(self):
3        print("Hello from A!")
4
5class B(A):
6    def greet(self):
7        super(B, self).greet()
8        print("Hello from B!")
9
10b = B()
11b.greet()

Output:

 
Hello from A!
Hello from B!

Without inheriting from object, super() would be ineffective or could result in errors.

Method Resolution Order (MRO)

The MRO defines the order in which base classes are searched when executing a method. In new-style classes, MRO uses the C3 algorithm, ensuring a more deterministic order:

python
1class X(object): pass
2class Y(object): pass
3class Z(X, Y): pass
4
5print(Z.__mro__)

Output:

 
(<class '__main__.Z'>, <class '__main__.X'>, <class '__main__.Y'>, <class 'object'>)

Summary Table

FeatureClassic ClassesNew-Style Classes
Base classNoneobject
Descriptor protocolNot supportedSupported
Method Resolution OrderDepth-first, left-to-rightC3 linearization
super() functionalityLimitedFull support
Common base type supportNoneUnified type system with object

Conclusion

In summary, inheriting from object when defining Python classes is essential for tapping into the full potential of Python's modern object-oriented capabilities. This practice encapsulates not only enhanced functionalities, like cooperative multiple inheritance and reliable property creation, but also aligns with Python's philosophy for uniformity and predictability.

Adopting new-style classes by inheriting from object is not just advantageous but necessary in the context of Python 3, paving the way toward a robust and clean application design.


Course illustration
Course illustration

All Rights Reserved.