@functools.singledispatch(default)
Transforms a function into a single-dispatch generic function.
To define a generic function, decorate it with the @singledispatch
decorator. Note that the dispatch happens on the type of the first argument, create your function accordingly:
1 2 3 4 5 6 | >>> from functools import singledispatch >>> @singledispatch ... def fun(arg, verbose=False): ... if verbose: ... print( "Let me just say," , end= " " ) ... print(arg) |
To add overloaded implementations to the function, use the register()
attribute of the generic function. It is a decorator, taking a type parameter and decorating a function implementing the operation for that type:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> @fun.register(int) ... def _(arg, verbose=False): ... if verbose: ... print( "Strength in numbers, eh?" , end= " " ) ... print(arg) ... >>> @fun.register(list) ... def _(arg, verbose=False): ... if verbose: ... print( "Enumerate this:" ) ... for i, elem in enumerate(arg): ... print(i, elem) |
To enable registering lambdas and pre-existing functions, the register()
attribute can be used in a functional form:
1 2 3 4 | >>> def nothing(arg, verbose=False): ... print( "Nothing." ) ... >>> fun.register(type(None), nothing) |
The register()
attribute returns the undecorated function which enables decorator stacking, pickling, as well as creating unit tests for each variant independently:
1 2 3 4 5 6 7 8 9 | >>> @fun.register(float) ... @fun.register(Decimal) ... def fun_num(arg, verbose=False): ... if verbose: ... print( "Half of your number:" , end= " " ) ... print(arg / 2) ... >>> fun_num is fun False |
When called, the generic function dispatches on the type of the first argument:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | >>> fun( "Hello, world." ) Hello, world. >>> fun( "test." , verbose=True) Let me just say, test. >>> fun(42, verbose=True) Strength in numbers, eh? 42 >>> fun([ 'spam' , 'spam' , 'eggs' , 'spam' ], verbose=True) Enumerate this : 0 spam 1 spam 2 eggs 3 spam >>> fun(None) Nothing. >>> fun(1.23) 0.615 |
Where there is no registered implementation for a specific type, its method resolution order is used to find a more generic implementation. The original function decorated with @singledispatch
is registered for the base object
type, which means it is used if no better implementation is found.
To check which implementation will the generic function choose for a given type, use the dispatch()
attribute:
1 2 3 4 | >>> fun.dispatch(float) < function fun_num at 0x1035a2840> >>> fun.dispatch(dict) # note: default implementation < function fun at 0x103fe0000> |
To access all registered implementations, use the read-only registry
attribute:
1 2 3 4 5 6 7 8 | >>> fun.registry.keys() dict_keys([<class 'NoneType' >, <class 'int' >, <class 'object' >, <class 'decimal.Decimal' >, <class 'list' >, <class 'float' >]) >>> fun.registry[float] < function fun_num at 0x1035a2840> >>> fun.registry[object] < function fun at 0x103fe0000> |
New in version 3.4.
Please login to continue.