- Trending Categories
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
Physics
Chemistry
Biology
Mathematics
English
Economics
Psychology
Social Studies
Fashion Studies
Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
__subclasscheck__ and __subclasshook__ in Python
Python, a generally adaptable and effective programming language, has picked up significant popularity over a long time. The item-oriented nature of Python lets within the execution of a few high-quality capacities, such as inheritance and polymorphism. In this post, we will delve into two lesser-recognized, yet charming techniques that allow for custom-designed inheritance checks in Python: subclasscheck and subclasshook.
What are Subclasscheck and Subclasshook?
In Python, it is not unusual to determine if a class is a subclass of some other class by utilizing the built-in issubclass() function. By default, this function checks the inheritance tree to decide the connection between lessons. However, Python also provides a manner to override this default behavior using the unique methods subclasscheck and subclasshook.
__subclasscheck__(cls) − This technique is called by using the issubclass() function to test if a category is a subclass of every other class. By default, it returns the result of the usual inheritance test, but it is able to be overridden to alternate this behavior.
__subclasshook__(cls) − This method can be defined in an abstract base class (ABC) to customize the subclass check performed by issubclass(). It is called by the default implementation of subclasscheck in the ABC.
The Subclasshook Method
To have a clear understanding of the working of the subclasshook method, let's go through an example. Suppose we've got an abstract base class referred to as 'Shape' with two required methods: 'area' and 'perimeter'. Any class that desires to be considered a subclass of 'Shape' must put into effect those methods.
Step 1 − Determine an abstract base Class 'Shape' with two specific methods: 'area' and 'perimeter'.
Step 2 − Generate a custom class 'Circle' that implements the specified methods 'area' and 'perimeter'.
Step 3 − Override the subclasshook method in the 'Shape' class to specify custom criteria for determining if a class is a subclass. In this situation, the standards are that the class ought to have the 'area' and 'perimeter' methods.
Step 4 − Use the issubclass() function to test if 'Circle' is a subclass of 'Shape'. With the custom subclasshook method, the result is 'True' because 'Circle' meets the custom criteria.
Example
Now, let's create a custom class 'Circle' that implements these methods −
from abc import ABCMeta, abstractmethod class Shape(metaclass=ABCMeta): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass class Circle: def __init__(self, radius): self.radius = radius def area(self): return 3.14 * self.radius * self.radius def perimeter(self): return 2 * 3.14 * self.radius print(issubclass(Circle, Shape))
Even though the 'Circle' class implements the required methods, the issubclass() function will still return 'False' when checking if 'Circle' is a subclass of 'Shape' −
Output
False
This is where the subclasshook method comes into play. We can override this method in the 'Shape' class to specify our custom criteria for determining if a class is a subclass −
Example
class Shape(metaclass=ABCMeta): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass @classmethod def __subclasshook__(cls, other): if cls is Shape: if all(hasattr(other, method) for method in ['area', 'perimeter']): return True return NotImplemented print(issubclass(Circle, Shape))
Output
Here is the output, if we check if 'Circle' is a subclass of 'Shape'.
True
The Subclasscheck Method
In some cases, you might want to override the subclasscheck method itself, rather than using subclasshook. This can offer extra first-class-grained control over the inheritance test. Here is an example −
Step 1 − Determine a custom base class 'CustomBase' that overrides the subclasscheck approach. Instead of testing for a general inheritance connection, we test if the subclass has a callable 'magic_attribute' approach.
Step 2 − Generate two classes, 'DerivedWithMagic' and 'DerivedWithoutMagic'. The former has the 'magic_attribute' method, while the latter does not.
Step 3 − Utilize the issubclass() function to test in case 'DerivedWithMagic' and 'DerivedWithoutMagic' are subclasses of 'CustomBase'. The conclusion is 'True' for 'DerivedWithMagic' since it has the desired 'magic_attribute' method, and 'False' for 'DerivedWithoutMagic' because it no longer has the specified method.
Example
class CustomBase: def __subclasscheck__(self, subclass): return (hasattr(sub class, "magic_attribute") and callable(getattr(subclass, "magic_attribute"))) class DerivedWithMagic: def magic_attribute(self): pass class DerivedWithoutMagic: pass print(issubclass(DerivedWithMagic, CustomBase)) print(issubclass(DerivedWithoutMagic, CustomBase))
Output
Here is the output, if we check if 'Circle' is a subclass of 'Shape'.
True False
Practical Use Cases
While the default inheritance mechanism in Python is suitable for most scenarios, there are cases where customizing subclass checks using __subclasscheck__ and __subclasshook__ can be beneficial −
**Protocol enforcement** − By using these methods, you can enforce certain protocols that subclasses must adhere to. In our preceding instance, we decided that any class treated as a subclass of 'Shape' has to perform the 'area' and 'perimeter' methods.
**Mixin lessons** − Mixin classes are created to give particular behaviors to other classes, but they are not meant to be used as standalone classes. You can use __subclasscheck__ or __subclasshook__ to define custom inheritance policies that identify classes by utilizing the mixin as subclasses, despite the fact that they do not inherit without delay from it.
**Loose coupling** − In some situations, it's beneficial to minimize dependencies between components in a software system. By using __subclasscheck__ and __subclasshook__, you can establish relationships between classes without having to create a rigid inheritance hierarchy.
Conclusion
The __subclasscheck__ and __subclasshook__ methods in Python offer a powerful way to customize inheritance checks. These methods can be especially helpful when you want to enforce specific requirements for subclass relationships or provide more flexible inheritance structures. By understanding and leveraging these special methods, you can create more adaptable and robust Python programs.