0
# Advanced Features
1
2
Advanced dispatching capabilities including conflict resolution, variadic dispatch, custom namespaces, signature analysis, and specialized tools for complex dispatch scenarios.
3
4
## Capabilities
5
6
### Variadic Dispatch
7
8
Support for functions that accept variable numbers of arguments with type constraints, enabling dispatch on argument count and types simultaneously.
9
10
```python { .api }
11
class VariadicSignatureMeta(type):
12
"""
13
Metaclass that overrides __getitem__ to generate variadic signature types.
14
Used internally by the Variadic class.
15
"""
16
17
class Variadic(metaclass=VariadicSignatureMeta):
18
"""
19
A class whose getitem method generates new types representing variadic signatures.
20
21
Usage:
22
- Variadic[int] for any number of int arguments
23
- Variadic[(int, str)] for any number of arguments that are int or str
24
25
Note: Most users should use list notation instead: [int] or [(int, str)]
26
27
Examples:
28
>>> Variadic[int] # any number of int arguments
29
<class 'multipledispatch.variadic.Variadic[int]'>
30
>>> Variadic[(int, str)] # any number of int or str arguments
31
<class 'multipledispatch.variadic.Variadic[(int, str)]'>
32
"""
33
34
class VariadicSignatureType(type):
35
"""
36
Type class for variadic signatures created by VariadicSignatureMeta.
37
Handles subclass checking and equality for variadic signature types.
38
"""
39
40
def __subclasscheck__(self, subclass):
41
"""
42
Check if subclass is compatible with this variadic signature.
43
44
Parameters:
45
- subclass: type - Type to check
46
47
Returns:
48
bool: True if subclass matches variadic signature
49
"""
50
51
def __eq__(self, other):
52
"""
53
Check equality with another variadic signature type.
54
55
Parameters:
56
- other: object - Object to compare with
57
58
Returns:
59
bool: True if both have same variadic type
60
"""
61
62
def isvariadic(obj):
63
"""
64
Check whether the type obj is variadic.
65
66
Parameters:
67
- obj: type - The type to check
68
69
Returns:
70
bool: True if type represents a variadic signature
71
"""
72
```
73
74
**Usage Examples:**
75
76
```python
77
from multipledispatch import dispatch
78
79
# Variable number of integers (using list notation)
80
@dispatch([int])
81
def sum_ints(*args):
82
return sum(args)
83
84
# Variable number of strings
85
@dispatch([str])
86
def concat_strings(*args):
87
return ''.join(args)
88
89
# Mixed: float followed by any number of int or str
90
@dispatch(float, [(int, str)])
91
def process_mixed(x, *args):
92
# Convert all args to numbers and sum with x
93
return x + sum(int(arg) for arg in args)
94
95
# Usage
96
sum_ints(1, 2, 3, 4) # -> 10
97
concat_strings("a", "b", "c") # -> "abc"
98
process_mixed(1.0, 2, '3', 4) # -> 10.0
99
process_mixed(2.0, '4', 6, 8) # -> 20.0
100
101
# The Variadic class is used internally but can be accessed:
102
from multipledispatch import Variadic
103
104
# This is equivalent to @dispatch([int]):
105
@dispatch(Variadic[int])
106
def internal_sum(*args):
107
return sum(args)
108
```
109
110
### Namespace Management
111
112
Custom namespaces for dispatch isolation, enabling multiple independent dispatch systems and avoiding conflicts between different parts of an application.
113
114
```python { .api }
115
# Global namespace (default)
116
global_namespace = dict # Automatically used when no namespace specified
117
118
# Custom namespace creation
119
def dispatch(*types, namespace=None):
120
"""
121
Dispatch decorator with namespace support.
122
123
Parameters:
124
- *types: Type signatures
125
- namespace: dict (optional) - Custom namespace for isolation
126
"""
127
```
128
129
**Usage Examples:**
130
131
```python
132
# Create isolated namespaces
133
math_namespace = {}
134
string_namespace = {}
135
136
# Math operations in isolated namespace
137
@dispatch(int, int, namespace=math_namespace)
138
def combine(x, y):
139
return x + y
140
141
# String operations in different namespace
142
@dispatch(str, str, namespace=string_namespace)
143
def combine(x, y):
144
return x + y
145
146
# Each namespace resolves independently
147
math_combine = math_namespace['combine']
148
string_combine = string_namespace['combine']
149
```
150
151
### Conflict Resolution and Ordering
152
153
Sophisticated conflict detection and resolution system that ensures deterministic dispatch behavior through topological ordering of type signatures.
154
155
```python { .api }
156
def halt_ordering():
157
"""
158
Temporarily disable signature ordering (DEPRECATED).
159
Used for performance during bulk registration.
160
"""
161
162
def restart_ordering(on_ambiguity=None):
163
"""
164
Re-enable signature ordering with ambiguity handling (DEPRECATED).
165
166
Parameters:
167
- on_ambiguity: callable (optional) - Handler for ambiguous signatures
168
"""
169
170
# Signature analysis functions
171
def supercedes(a, b):
172
"""
173
Check if signature A is more specific than signature B.
174
175
Parameters:
176
- a: tuple - First signature
177
- b: tuple - Second signature
178
179
Returns:
180
bool: True if A supercedes B
181
"""
182
183
def ambiguous(a, b):
184
"""
185
Check if two signatures are ambiguous (neither supercedes the other).
186
187
Parameters:
188
- a: tuple - First signature
189
- b: tuple - Second signature
190
191
Returns:
192
bool: True if signatures are ambiguous
193
"""
194
195
def ambiguities(signatures):
196
"""
197
Find all ambiguous signature pairs in a collection.
198
199
Parameters:
200
- signatures: iterable - Collection of type signatures
201
202
Returns:
203
set: Pairs of ambiguous signatures
204
"""
205
206
def super_signature(signatures):
207
"""
208
Generate a signature that would break ambiguities between given signatures.
209
210
Parameters:
211
- signatures: list - List of ambiguous signatures
212
213
Returns:
214
list: Super signature that disambiguates the inputs
215
"""
216
217
class AmbiguityWarning(UserWarning):
218
"""
219
Warning issued when ambiguous type signatures are detected during dispatch registration.
220
"""
221
```
222
223
**Usage Examples:**
224
225
```python
226
from multipledispatch.conflict import supercedes, ambiguous
227
228
# Check signature relationships
229
sig1 = (int, int)
230
sig2 = (object, object)
231
232
print(supercedes(sig1, sig2)) # True - int is more specific than object
233
234
# Example of ambiguous signatures that would cause warnings
235
from multipledispatch import dispatch
236
237
@dispatch(int, str)
238
def process(x, y):
239
return f"int-str: {x}-{y}"
240
241
@dispatch(str, int)
242
def process(x, y):
243
return f"str-int: {x}-{y}"
244
245
# These are ambiguous - neither is more specific
246
# The library will warn and establish consistent ordering
247
```
248
249
### Signature Analysis and Utilities
250
251
Tools for analyzing type signatures, managing dispatch state, and debugging dispatch behavior.
252
253
```python { .api }
254
def typename(type_obj):
255
"""
256
Get readable name for a type or tuple of types.
257
258
Parameters:
259
- type_obj: type or tuple - Type(s) to get name for
260
261
Returns:
262
str: Human-readable type name
263
"""
264
265
def str_signature(signature):
266
"""
267
Create string representation of a type signature.
268
269
Parameters:
270
- signature: tuple - Type signature
271
272
Returns:
273
str: String representation
274
"""
275
276
def source(func):
277
"""
278
Get source code for a function.
279
280
Parameters:
281
- func: callable - Function to inspect
282
283
Returns:
284
str: Source code
285
"""
286
287
class AmbiguityWarning(UserWarning):
288
"""
289
Warning issued when ambiguous signatures are detected.
290
"""
291
```
292
293
### Dispatcher Introspection
294
295
Advanced inspection capabilities for debugging and analyzing dispatch behavior.
296
297
```python { .api }
298
class Dispatcher:
299
def help(self, *args, **kwargs):
300
"""
301
Display help information for dispatched function.
302
303
Parameters:
304
- *args: Type signature to get help for (optional)
305
"""
306
307
def source(self, *args, **kwargs):
308
"""
309
Display source code for specific implementation.
310
311
Parameters:
312
- *args: Type signature to get source for (optional)
313
"""
314
315
def dispatch_iter(self, *types):
316
"""
317
Iterator over all possible implementations for given types.
318
319
Parameters:
320
- *types: Types to find implementations for
321
322
Yields:
323
callable: Implementation functions in priority order
324
"""
325
326
@property
327
def ordering(self):
328
"""
329
Get the current signature ordering for this dispatcher.
330
331
Returns:
332
list: Ordered list of signatures from most to least specific
333
"""
334
```
335
336
**Usage Examples:**
337
338
```python
339
from multipledispatch import Dispatcher
340
341
# Create dispatcher for inspection
342
calc = Dispatcher('calc')
343
344
@calc.register(int, int)
345
def calc_impl(x, y):
346
return x + y
347
348
@calc.register(float, float)
349
def calc_impl(x, y):
350
return x + y
351
352
# Inspect dispatcher state
353
calc.help() # Show all implementations
354
calc.help(int, int) # Show specific implementation
355
calc.source(int, int) # Show source code
356
357
# Check ordering
358
print(calc.ordering) # [(int, int), (float, float), ...]
359
360
# Iterate through possible implementations
361
for impl in calc.dispatch_iter(int, int):
362
print(f"Implementation: {impl}")
363
```
364
365
### Performance and Caching
366
367
Built-in caching system and performance optimization features for high-frequency dispatch scenarios.
368
369
```python { .api }
370
class Dispatcher:
371
# Internal caching system
372
_cache = dict # Type signature -> implementation cache
373
374
def reorder(self, on_ambiguity=None):
375
"""
376
Recompute signature ordering and clear cache.
377
378
Parameters:
379
- on_ambiguity: callable (optional) - Ambiguity handler
380
"""
381
```
382
383
**Performance Characteristics:**
384
385
- **O(1) dispatch** after cache warming for repeated type patterns
386
- **Static conflict detection** at registration time prevents runtime errors
387
- **Topological ordering** ensures consistent, deterministic resolution
388
- **Inheritance-aware caching** handles subclass relationships efficiently
389
390
**Example:**
391
392
```python
393
# High-performance dispatcher with caching
394
@dispatch(int, int)
395
def fast_add(x, y):
396
return x + y
397
398
# First call builds cache
399
result1 = fast_add(1, 2) # Slower - cache miss
400
401
# Subsequent calls with same types are cached
402
result2 = fast_add(3, 4) # Faster - cache hit
403
result3 = fast_add(5, 6) # Faster - cache hit
404
```
405
406
### Utility Functions
407
408
Core utility functions used internally by the dispatch system and available for advanced use cases.
409
410
```python { .api }
411
def typename(type_obj):
412
"""
413
Get readable name for a type or tuple of types.
414
415
Parameters:
416
- type_obj: type or tuple - Type(s) to get name for
417
418
Returns:
419
str: Human-readable type name
420
"""
421
422
def str_signature(signature):
423
"""
424
Create string representation of a type signature.
425
426
Parameters:
427
- signature: tuple - Type signature
428
429
Returns:
430
str: String representation (e.g., "int, float")
431
"""
432
433
def source(func):
434
"""
435
Get source code for a function with file information.
436
437
Parameters:
438
- func: callable - Function to inspect
439
440
Returns:
441
str: Source code with file path header
442
"""
443
444
def warning_text(name, ambiguities):
445
"""
446
Generate warning text for ambiguous signatures.
447
448
Parameters:
449
- name: str - Function name
450
- ambiguities: set - Pairs of ambiguous signatures
451
452
Returns:
453
str: Formatted warning message with suggested fixes
454
"""
455
456
def expand_tuples(signature_list):
457
"""
458
Expand union types in signature list into individual signatures.
459
460
Parameters:
461
- signature_list: list - List containing types and union tuples
462
463
Returns:
464
list: All possible signature combinations
465
"""
466
467
def groupby(func, seq):
468
"""
469
Group a collection by a key function.
470
471
Parameters:
472
- func: callable - Key function to group by
473
- seq: iterable - Sequence to group
474
475
Returns:
476
dict: Grouped items by key
477
"""
478
479
def reverse_dict(dependency_dict):
480
"""
481
Reverse direction of dependency dictionary.
482
483
Parameters:
484
- dependency_dict: dict - Dict mapping keys to dependent values
485
486
Returns:
487
dict: Reversed dependency mapping
488
"""
489
490
def raises(error_type, func):
491
"""
492
Test if function raises specified exception type.
493
494
Parameters:
495
- error_type: Exception - Exception type to check for
496
- func: callable - Function to test
497
498
Returns:
499
bool: True if function raises the exception
500
"""
501
```
502
503
**Usage Examples:**
504
505
```python
506
from multipledispatch.utils import typename, str_signature
507
from multipledispatch.conflict import supercedes, ambiguous
508
509
# Type name utilities
510
print(typename(int)) # -> "int"
511
print(typename((int, float))) # -> "(int, float)"
512
513
# Signature analysis
514
sig1 = (int, str)
515
sig2 = (object, str)
516
print(str_signature(sig1)) # -> "int, str"
517
print(supercedes(sig1, sig2)) # -> True (int more specific than object)
518
519
# Check for ambiguity
520
sig3 = (str, int)
521
print(ambiguous(sig1, sig3)) # -> True (neither supercedes the other)
522
```