NumPyOverloader#
- class overload_numpy.NumPyOverloader
Bases:
Mapping[str,Dispatcher[Any]]Register
numpyfunction overrides.This mapping works in conjunction with a mixin (
NPArrayFuncOverloadMixin,NPArrayUFuncOverloadMixin, orNPArrayOverloadMixin) to register and implement overrides with__array_function__and__array_ufunc__.Methods
assists()Register an
__array_function__assistance function.get(k[,d])Register an
__array_function__implementation object.items()Return registry items (str, dispatchers).
keys()Return registry keys (
str).values()Return registry values (dispatchers).
Examples
First, some imports:
>>> from dataclasses import dataclass, fields >>> from typing import ClassVar >>> import numpy as np >>> from overload_numpy import NumPyOverloader, NPArrayFuncOverloadMixin
Now we can define a
NumPyOverloaderinstance:>>> W_FUNCS = NumPyOverloader()
The overloads apply to an array wrapping class. Let’s define one:
>>> @dataclass ... class Wrap1D(NPArrayFuncOverloadMixin): ... '''A simple array wrapper.''' ... x: np.ndarray ... NP_OVERLOADS: ClassVar[NumPyOverloader] = W_FUNCS
Now
numpyfunctions can be overloaded and registered forWrap1D.>>> @W_FUNCS.implements(np.concatenate, Wrap1D) ... def concatenate(vecs): ... VT = type(vecs[0]) ... return VT(*(np.concatenate(tuple(getattr(v, f.name) for v in vecs)) ... for f in fields(VT)))
Time to check this works:
>>> vec1d = Wrap1D(np.arange(3)) >>> np.concatenate((vec1d, vec1d)) Wrap1D(x=array([0, 1, 2, 0, 1, 2]))
Initialize for
dataclass-decorated subclasses.Methods
assists()Register an
__array_function__assistance function.get(k[,d])Register an
__array_function__implementation object.items()Return registry items (str, dispatchers).
keys()Return registry keys (
str).values()Return registry values (dispatchers).
Methods Summary
assists()Register an
__array_function__assistance function.Register an
__array_function__implementation object.items()Return registry items (str, dispatchers).
keys()Return registry keys (
str).values()Return registry values (dispatchers).
Methods Documentation
- assists(numpy_funcs: UFuncLike, /, dispatch_on: type, *, types: type | TypeConstraint | Collection[type | TypeConstraint] | None, methods: Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat'] | Set[Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat']]) OverloadUFuncDecorator[AssistsUFunc]#
- assists(numpy_funcs: FunctionType, /, dispatch_on: type, *, types: type | TypeConstraint | Collection[type | TypeConstraint] | None, methods: Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat'] | Set[Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat']]) OverloadFuncDecorator[AssistsFunc]
- assists(numpy_funcs: set[Callable[..., Any] | UFuncLike], /, dispatch_on: type, *, types: type | TypeConstraint | Collection[type | TypeConstraint] | None = None, methods: Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat'] | Set[Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat']] = '__call__') AssistsManyDecorator
Register an
__array_function__assistance function.This is a decorator factory, returning
decorator, which registers the decorated function as an overload method fornumpyfunctionnumpy_funcfor a class of typedispatch_on.- Parameters:
- assists
python:callable()[…,Any], positional-only The
numpyfunction(s) that is(/are) being overloaded.- dispatch_ontype
The class type for which the overload implementation is being registered.
- typestype or
TypeConstraintorCollectionthereof orpython:None, keyword-only The types of the arguments of
assists. See__array_function__for details. Only used if a function (notufunc) is being overridden. IfNonethendispatch_onmust have class-level attributeNP_FUNC_TYPESspecifying the types.- methods{‘__call__’, ‘at’, ‘accumulate’, ‘outer’, ‘reduce’, ‘reduceat’} or
setthereof, keyword-only The
ufuncmethods for which this override applies. Default is just “__call__”. Only used if aufunc(not function) is being overridden.
- assists
- Returns:
AssistsManyDecoratorDecorator to register the wrapped function(s). This decorator should never be called by the user.
Examples
There’s a fair bit of setup required:
>>> from dataclasses import dataclass, fields >>> from typing import ClassVar >>> import numpy as np >>> from overload_numpy import NumPyOverloader, NPArrayFuncOverloadMixin
>>> W_FUNCS = NumPyOverloader()
>>> @dataclass ... class Wrap1D(NPArrayFuncOverloadMixin): ... '''A simple array wrapper.''' ... x: np.ndarray ... NP_OVERLOADS: ClassVar[NumPyOverloader] = W_FUNCS
>>> w1d = Wrap1D(np.arange(3))
Now we can register
assistsfunctions.>>> stack_funcs = {np.vstack, np.hstack, np.dstack, np.column_stack, np.row_stack} >>> @W_FUNCS.assists(stack_funcs, types=Wrap1D, dispatch_on=Wrap1D) ... def stack_assists(dispatch_on, func, vecs, *args, **kwargs): ... cls = type(vecs[0]) ... return cls(*(func(tuple(getattr(v, f.name) for v in vecs), *args, **kwargs) ... for f in fields(cls)))
Checking this works:
>>> np.vstack((w1d, w1d)) Wrap1D(x=array([[0, 1, 2], [0, 1, 2]]))
>>> np.hstack((w1d, w1d)) Wrap1D(x=array([0, 1, 2, 0, 1, 2]))
assistsalso works forufunc:>>> add_funcs = {np.add, np.subtract} >>> @W_FUNCS.assists(add_funcs, types=Wrap1D, dispatch_on=Wrap1D) ... def add_assists(cls, func, w1, w2, *args, **kwargs): ... return cls(*(func(getattr(w1, f.name), getattr(w2, f.name), *args, **kwargs) ... for f in fields(cls)))
Checking this works:
>>> np.subtract(w1d, w1d) Wrap1D(x=array([0, 0, 0]))
We can also to implement the
ufuncmethods, like``accumulate``, for all theadd_funcsoverloads:>>> @add_assists.register("accumulate") ... def add_accumulate_assists(cls, func, w1, *args, **kwargs): ... return cls(*(func(getattr(w1, f.name), *args, **kwargs) ... for f in fields(cls)))
>>> np.subtract.accumulate(w1d) Wrap1D(x=array([ 0, -1, -3]))
- implements(implements: UFuncLike, /, dispatch_on: type, *, types: type | TypeConstraint | Collection[type | TypeConstraint] | None = None, methods: Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat'] | Set[Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat']] = '__call__') OverloadUFuncDecorator[ImplementsUFunc]#
- implements(implements: FunctionType, /, dispatch_on: type, *, types: type | TypeConstraint | Collection[type | TypeConstraint] | None = None, methods: Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat'] | Set[Literal['__call__', 'at', 'accumulate', 'outer', 'reduce', 'reduceat']] = '__call__') OverloadFuncDecorator[ImplementsFunc]
Register an
__array_function__implementation object.This is a decorator factory, returning
decorator, which registers the decorated function as an overload method fornumpyfunctionimplementsfor a class of typedispatch_on.- Parameters:
- implements
python:callable()[…,Any], positional-only The
numpyfunction that is being overloaded.- dispatch_ontype
The class type for which the overload implementation is being registered.
- typestype or
TypeConstraintorCollectionthereof orpython:None, keyword-only The types of the arguments of
implements. See__array_function__. IfNonethendispatch_onmust have class-level attributeNP_FUNC_TYPESspecifying the types.- methods{‘__call__’, ‘accumulate’, ‘outer’, ‘reduce’} or
python:None, keyword-only numpy.ufuncmethods.
- implements
- Returns:
ImplementsFuncDecoratorDecorator to register the wrapped function.
Examples
There’s a fair bit of setup required:
>>> from dataclasses import dataclass, fields >>> from typing import ClassVar >>> import numpy as np >>> from overload_numpy import NumPyOverloader, NPArrayFuncOverloadMixin
>>> W_FUNCS = NumPyOverloader()
>>> @dataclass ... class Wrap1D(NPArrayFuncOverloadMixin): ... '''A simple array wrapper.''' ... x: np.ndarray ... NP_OVERLOADS: ClassVar[NumPyOverloader] = W_FUNCS
>>> w1d = Wrap1D(np.arange(3))
Now we can register an
implementsfunctions.>>> @W_FUNCS.implements(np.concatenate, Wrap1D) # overriding ... def concatenate(vecs): ... VT = type(vecs[0]) ... return VT(*(np.concatenate(tuple(getattr(v, f.name) for v in vecs)) ... for f in fields(VT)))
Checking it works:
>>> vec1d = Wrap1D(np.arange(3))
>>> newvec = np.concatenate((vec1d, vec1d)) >>> newvec Vector2D(x=array([0, 1, 2, 0, 1, 2]), y=array([3, 4, 5, 3, 4, 5]))
implementsalso works forufunc:>>> @W_FUNCS.implements(np.add, Wrap1D) ... def add(w1, w2): ... return Wrap1D(np.add(w1.x, w2.x))
>>> np.add(w1d, w1d) Wrap1D(x=array([0, 2, 4]))
- items() ItemsView[str, All_Dispatchers]#
Return registry items (str, dispatchers).
- keys() KeysView[str]#
Return registry keys (
str).
- values() ValuesView[All_Dispatchers]#
Return registry values (dispatchers).