The issubclass(class, classinfo) function determines whether a specified class is a direct or indirect subclass of another class, returning True or False.
Type Hierarchy Verification: In Python, a class is considered a subclass of itself (reflexive property). The second argument can be a single class or a tuple of classes evaluated with logical OR semantics. While isinstance() inspects object instances, issubclass() strictly inspects class types. For dynamic introspection, see built-in functions like callable(), vars(), and getattr().
The issubclass() function accepts a target class and one or more candidate parent types:
is_child = issubclass(class, classinfo)
| Parameter | Type Accepted | Behavioral Details |
|---|---|---|
class |
type (class object) |
The class being inspected. Must be a class object; passing an instance raises a TypeError. |
classinfo |
type or tuple of types |
A single class, or a tuple containing classes against which the first parameter is evaluated. |
| Return Value | bool |
Returns True if class derives from classinfo; otherwise returns False. |
Python supports multi-level inheritance hierarchies. issubclass() recognizes both direct child classes and distant ancestors:
class Animal:
home = "Jungle"
class Wild(Animal):
weight = 200
class Bird(Wild):
name = "Eagle"
# 1. Direct subclass
print("Wild is subclass of Animal:", issubclass(Wild, Animal))
# 2. Indirect (multi-level) subclass
print("Bird is subclass of Animal:", issubclass(Bird, Animal))
# 3. Reflexive property: every class is a subclass of itself
print("Wild is subclass of Wild:", issubclass(Wild, Wild))
# 4. Asymmetry: parents are not subclasses of their children
print("Animal is subclass of Wild:", issubclass(Animal, Wild))
Output:
Wild is subclass of Animal: True
Bird is subclass of Animal: True
Wild is subclass of Wild: True
Animal is subclass of Wild: False
You can pass a tuple of classes as the second argument. If the target class derives from any class in the tuple, issubclass() returns True:
class Vehicle:
pass
class Truck(Vehicle):
pass
# Evaluates with logical OR semantics across candidate types
candidates = (str, list, Vehicle)
print("Truck matches candidate tuple:", issubclass(Truck, candidates))
unrelated = (int, dict)
print("Truck matches unrelated tuple:", issubclass(Truck, unrelated))
Output:
Truck matches candidate tuple: True
Truck matches unrelated tuple: False
issubclass() vs. isinstance(): Classes vs. Instances 🔝Distinguish between class-level type hierarchy inspection and instance verification:
issubclass(ClassA, ClassB): Compares two class objects. Passing an instance raises a TypeError.isinstance(instance, ClassB): Checks if an instantiated object belongs to a class or derives from it.class Shape:
pass
class Circle(Shape):
pass
c = Circle() # Instantiated object
print("isinstance(c, Shape):", isinstance(c, Shape))
print("issubclass(Circle, Shape):", issubclass(Circle, Shape))
try:
issubclass(c, Shape)
except TypeError as err:
print("Caught TypeError:", err)
Output:
isinstance(c, Shape): True
issubclass(Circle, Shape): True
Caught TypeError: issubclass() arg 1 must be a class
Python's Abstract Base Classes (via collections.abc) support virtual subtyping without requiring explicit inheritance. Built-in types like list or dict are recognized virtual subclasses:
import collections.abc
print("list is Sequence: ", issubclass(list, collections.abc.Sequence))
print("dict is Mapping: ", issubclass(dict, collections.abc.Mapping))
print("tuple is Sequence:", issubclass(tuple, collections.abc.Sequence))
Output:
list is Sequence: True
dict is Mapping: True
tuple is Sequence: True
Exploring Python's built-in type relationships reveals interesting architectural traits:
# 1. Booleans are subclasses of integers
print("issubclass(bool, int):", issubclass(bool, int))
# 2. Everything is a subclass of object
print("issubclass(int, object):", issubclass(int, object))
print("issubclass(int, float): ", issubclass(int, float))
Output:
issubclass(bool, int): True
issubclass(int, object): True
issubclass(int, float): False
Ensure third-party extensions inherit from your designated plugin interface before loading:
class BasePlugin:
def execute(self):
raise NotImplementedError
class AuditPlugin(BasePlugin):
def execute(self):
return "Audit executed"
class RoguePlugin:
pass
def register_plugin(plugin_cls):
if not isinstance(plugin_cls, type):
raise TypeError("Expected a class type")
if not issubclass(plugin_cls, BasePlugin):
raise ValueError(f"{plugin_cls.__name__} must inherit from BasePlugin")
return f"Plugin {plugin_cls.__name__} registered."
print(register_plugin(AuditPlugin))
try:
register_plugin(RoguePlugin)
except ValueError as err:
print("Registration rejected:", err)
Output:
Plugin AuditPlugin registered.
Registration rejected: RoguePlugin must inherit from BasePlugin
Validate that custom application exceptions properly inherit from standard Exception:
class AppDatabaseError(Exception):
pass
def is_standard_exception(exc_cls: type) -> bool:
return issubclass(exc_cls, Exception) and exc_cls is not KeyboardInterrupt
print("AppDatabaseError standard:", is_standard_exception(AppDatabaseError))
print("KeyboardInterrupt standard:", is_standard_exception(KeyboardInterrupt))
Output:
AppDatabaseError standard: True
KeyboardInterrupt standard: False
issubclass(obj, Class) immediately raises a TypeError. Use isinstance(obj, Class) instead.
x = 10
# Trap: passing instance raises TypeError
try:
issubclass(x, int)
except TypeError as err:
print("TypeError caught:", err)
print("Using type():", issubclass(type(x), int))
print("Using isinstance():", isinstance(x, int))
Output:
TypeError caught: issubclass() arg 1 must be a class
Using type(): True
Using isinstance(): True
Practice hierarchy validation, virtual ABC subtyping, and plugin guards in our companion Jupyter Notebook:
Explore interactive code cells, implement class hierarchy checkers, test virtual ABC registrations, and run self-validating assertions.
View on GitHub Run in Google ColabRun these unit checks directly in Python or your local environment to verify issubclass() mechanics:
def test_issubclass_mechanics():
class A:
pass
class B(A):
pass
class C(B):
pass
assert issubclass(B, A) is True
assert issubclass(C, A) is True
assert issubclass(A, B) is False
assert issubclass(C, (A, str)) is True
assert issubclass(bool, int) is True
try:
issubclass(C(), A)
assert False
except TypeError:
pass
print("All issubclass() unit assertions passed! 100% verified.")
test_issubclass_mechanics()
Output:
All issubclass() unit assertions passed! 100% verified.
Checks if an instantiated object is an instance of a specified class or tuple of classes.
Checks if an object or class constructor can be called using invocation parentheses.
Returns the __dict__ namespace mapping for an object, class, or local scope.
Returns the exact type of an object or constructs a new class dynamically.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.