safe_is_instance Guide
Check if an object is an instance of a class by its fully qualified name, without importing the class.
Overview
safe_is_instance allows you to check if an object is an instance of a class identified only by its full class path (e.g., "mypackage.models.BaseNode"), without importing the target class.
Key Benefits:
Avoids circular imports
Works with classes that may not be installed
Recognizes subclasses (full MRO support)
Cached for performance
Basic Usage
from genro_toolbox import safe_is_instance
# Check built-in types
safe_is_instance(42, "builtins.int") # True
safe_is_instance("hello", "builtins.str") # True
safe_is_instance([1, 2, 3], "builtins.list") # True
safe_is_instance({"a": 1}, "builtins.dict") # True
Custom Classes
from genro_toolbox import safe_is_instance
class MyClass:
pass
obj = MyClass()
# Use full qualified name: module.ClassName
safe_is_instance(obj, f"{MyClass.__module__}.{MyClass.__qualname__}") # True
Subclass Recognition
safe_is_instance recognizes the entire inheritance chain:
class GrandParent:
pass
class Parent(GrandParent):
pass
class Child(Parent):
pass
obj = Child()
# All return True
safe_is_instance(obj, f"{Child.__module__}.{Child.__qualname__}")
safe_is_instance(obj, f"{Parent.__module__}.{Parent.__qualname__}")
safe_is_instance(obj, f"{GrandParent.__module__}.{GrandParent.__qualname__}")
safe_is_instance(obj, "builtins.object") # Ultimate base class
Multiple Inheritance
Works correctly with multiple inheritance:
class MixinA:
pass
class MixinB:
pass
class Derived(MixinA, MixinB):
pass
obj = Derived()
# Recognizes all classes in MRO
safe_is_instance(obj, f"{Derived.__module__}.{Derived.__qualname__}") # True
safe_is_instance(obj, f"{MixinA.__module__}.{MixinA.__qualname__}") # True
safe_is_instance(obj, f"{MixinB.__module__}.{MixinB.__qualname__}") # True
Use Cases
Avoiding Circular Imports
# In module_a.py
from genro_toolbox import safe_is_instance
def process_node(obj):
# Avoid importing module_b which imports module_a
if safe_is_instance(obj, "module_b.Node"):
return handle_node(obj)
return handle_other(obj)
Plugin System
from genro_toolbox import safe_is_instance
def load_plugin(obj):
"""Load plugin without requiring plugin base class import."""
if safe_is_instance(obj, "myapp.plugins.BasePlugin"):
obj.initialize()
return obj
raise TypeError("Not a valid plugin")
Optional Dependencies
from genro_toolbox import safe_is_instance
def serialize(obj):
"""Serialize object, handling optional pandas DataFrames."""
if safe_is_instance(obj, "pandas.core.frame.DataFrame"):
return obj.to_dict()
if safe_is_instance(obj, "numpy.ndarray"):
return obj.tolist()
return str(obj)
Edge Cases
Non-existent Classes
Returns False for non-existent class names:
class MyClass:
pass
obj = MyClass()
safe_is_instance(obj, "fake.module.NonExistentClass") # False
Partial Class Names
Requires fully qualified name (module + class):
class MyClass:
pass
obj = MyClass()
safe_is_instance(obj, "MyClass") # False (no module)
Nested Classes
Nested classes have qualified names with dots:
class Outer:
class Inner:
pass
obj = Outer.Inner()
# Use qualname which includes the nesting
safe_is_instance(obj, f"{Outer.Inner.__module__}.{Outer.Inner.__qualname__}") # True
Performance
safe_is_instance uses LRU caching for optimal performance:
# First call populates cache
result1 = safe_is_instance(obj1, "mymodule.MyClass")
# Subsequent calls use cached MRO lookup
result2 = safe_is_instance(obj2, "mymodule.MyClass") # Fast!
The MRO (Method Resolution Order) fullnames are cached per class, so repeated checks on objects of the same class are very efficient.
API Reference
def safe_is_instance(obj: Any, class_full_name: str) -> bool:
"""
Return True if obj is an instance of the class identified by
class_full_name or any of its subclasses — without importing
the class.
Args:
obj: The object to check.
class_full_name: The fully qualified class name,
e.g. "mypkg.models.BaseNode".
Returns:
True if obj is an instance of the class, False otherwise.
"""
See Also
SmartOptions Guide - Option merging and filtering
extract_kwargs Guide - Kwargs extraction decorator
API Reference - Complete API documentation