Multiple dispatch implementation for Python that enables function dispatching based on types of all non-keyword arguments
—
Essential dispatching features that form the foundation of multiple dispatch in Python. This includes the main dispatch decorator, programmatic dispatch management through the Dispatcher class, and comprehensive type system support.
The primary interface for creating dispatched functions using the @dispatch decorator with automatic type resolution and inheritance support.
def dispatch(*types, **kwargs):
"""
Decorator for creating dispatched functions based on argument types.
Parameters:
- *types: Type signatures for dispatch (e.g., int, str, (int, float))
- namespace: dict (optional) - Custom namespace for dispatch isolation
Returns:
Decorator function that registers implementations
Raises:
TypeError: If types are invalid
"""Usage Examples:
# Basic type dispatch
@dispatch(int, int)
def add(x, y):
return x + y
@dispatch(str, str)
def add(x, y):
return x + y
# Union types (multiple acceptable types)
@dispatch((int, float), (int, float))
def multiply(x, y):
return x * y
# Custom namespace
my_namespace = {}
@dispatch(int, namespace=my_namespace)
def process(x):
return x * 2Programmatic dispatch management for advanced use cases where decorators are insufficient or dynamic dispatch registration is needed.
class Dispatcher:
"""
Manages multiple implementations of a function with type-based dispatch.
"""
def __init__(self, name, doc=None):
"""
Initialize a new dispatcher.
Parameters:
- name: str - Name of the dispatched function
- doc: str (optional) - Documentation string for the dispatcher
"""
def register(self, *types, **kwargs):
"""
Register a new implementation for the given type signature.
Parameters:
- *types: Type signature (e.g., int, str, (int, float))
- **kwargs: Additional registration options
Returns:
Decorator function for the implementation
"""
def add(self, signature, func):
"""
Add new types/method pair to dispatcher.
Parameters:
- signature: tuple - Type signature
- func: callable - Implementation function
"""
def dispatch(self, *types):
"""
Determine appropriate implementation for this type signature.
This method is internal. Users should call this object as a function.
Implementation resolution occurs within the __call__ method.
Parameters:
- *types: Types to dispatch on
Returns:
callable: Best matching implementation
Raises:
MDNotImplementedError: If no suitable implementation found
"""
def resolve(self, types):
"""
Determine appropriate implementation for this type signature (DEPRECATED).
.. deprecated:: 0.4.4
Use dispatch(*types) instead
Parameters:
- types: tuple - Type signature
Returns:
callable: Best matching implementation
"""
def __call__(self, *args, **kwargs):
"""
Execute dispatch based on argument types.
Parameters:
- *args: Arguments to dispatch on
- **kwargs: Keyword arguments passed to implementation
Returns:
Result of dispatched function
"""Usage Examples:
# Create dispatcher programmatically
math_ops = Dispatcher('math_ops')
@math_ops.register(int, int)
def math_ops_impl(x, y):
return x + y
@math_ops.register(str, str)
def math_ops_impl(x, y):
return x + y
result = math_ops(1, 2) # -> 3
result = math_ops("a", "b") # -> "ab"
# Direct registration
def float_add(x, y):
return float(x + y)
math_ops.add((float, float), float_add)Specialized dispatcher for instance methods that automatically handles self parameter and integrates with Python's descriptor protocol.
class MethodDispatcher(Dispatcher):
"""
Dispatcher specialized for instance methods.
Inherits from Dispatcher with method-specific behavior.
"""
def __get__(self, instance, owner):
"""
Descriptor protocol implementation for method binding.
Parameters:
- instance: Object instance (or None for class access)
- owner: Owner class
Returns:
Bound method dispatcher
"""Usage Examples:
class Calculator:
add = MethodDispatcher('add')
@add.register(object, int, int)
def add_impl(self, x, y):
return x + y
@add.register(object, str, str)
def add_impl(self, x, y):
return x + y
calc = Calculator()
result = calc.add(1, 2) # -> 3
result = calc.add("a", "b") # -> "ab"Comprehensive support for Python's type system including inheritance, abstract base classes, and custom type checking.
def ismethod(func):
"""
Determine if function is a method during class definition.
Parameters:
- func: callable - Function to check
Returns:
bool: True if func is a method
"""Supported Type Features:
int, float, str, list, dict, etc.(int, float) for accepting multiple typescollections.abc.Iterator, numbers.Number, etc.'MyClass' for forward references during class definitionExamples:
from collections.abc import Iterator
from numbers import Number
@dispatch(Iterator)
def process_iterable(items):
return list(items)
@dispatch(Number, Number)
def calculate(x, y):
return x * y
# Works with inheritance
class Animal:
pass
class Dog(Animal):
pass
@dispatch(Animal)
def speak(animal):
return "Generic animal sound"
@dispatch(Dog) # More specific, takes precedence
def speak(dog):
return "Woof!"
dog = Dog()
speak(dog) # -> "Woof!" (uses more specific implementation)Structured error handling for dispatch failures and type resolution issues.
class MDNotImplementedError(NotImplementedError):
"""
Exception raised when no suitable implementation is found for given types.
Subclass of NotImplementedError with dispatch-specific context.
"""Example:
@dispatch(int)
def process(x):
return x * 2
try:
result = process("string") # No str implementation
except MDNotImplementedError as e:
print(f"No implementation found: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-multipledispatch