ndtools#

Release Python Downloads Tests

Collection of tools to extend multidimensional array operations

Installation#

pip install ndtools

Usage#

Comparison#

ndtools provides total_equality and total_ordering class decorators that fill in missing multidimensional equality and ordering methods, respectively. total_equality will fill in missing __ne__ from user-defined __eq__ or missing __eq__ from user-defined __ne__. The following example implements an object that checks whether each array element is even or not:

import numpy as np
from ndtools import total_equality

@total_equality
class Even:
    def __eq__(self, array):
        return array % 2 == 0

Even() == np.arange(3)  # -> array([True, False, True])
Even() != np.arange(3)  # -> array([False, True, False])

It also supports a more intuitive notation with the array written on the left-hand side and the object on the right-hand side:

np.arange(3) == Even()  # -> array([True, False, True])
np.arange(3) != Even()  # -> array([False, True, False])

total_ordering will fill in missing ordering operators (__ge__, __gt__, __le__, __lt__). As with functools.total_ordering, at least one of them, and __eq__ or __ne__ must be user-defined. The following example implements a range object that defines equivalence with a certain range:

import numpy as np
from dataclasses import dataclass
from ndtools import total_ordering

@dataclass
@total_ordering
class Range:
    lower: float
    upper: float

    def __eq__(self, array):
        return (array >= self.lower) & (array < self.upper)

    def __ge__(self, array):
        return array < self.upper

Range(1, 2) == np.arange(3)  # -> array([False, True, False])
Range(1, 2) < np.arange(3)   # -> array([False, False, True])
Range(1, 2) > np.arange(3)   # -> array([True, False, False])

It also supports a more intuitive notation with the array written on the left-hand side and the object on the right-hand side:

np.arange(3) == Range(1, 2) # -> array([False, True, False])
np.arange(3) < Range(1, 2)  # -> array([True, False, False])
np.arange(3) > Range(1, 2)  # -> array([False, False, True])

[!TIP] Mix-in versions of them, TotalEquality and TotalOrdering, are also available.