I have a little helper class:
class AnyOf(object):
def __init__(self, *args):
self.elements = args
def __eq__(self, other):
return other in self.elements
This lets me do sweet magic like:
>>> arr = np.array([1,2,3,4,5])
>>> arr == AnyOf(2,3)
np.array([False, True, True, False, False])
without having to use a list comprehension (as in np.array(x in (2,3) for x in arr).
(I maintain a UI that lets (trusted) users type in arbitrary code, and a == AnyOf(1,2,3) is a lot more palatable than a list comprehension to the non-technically savvy user.)
However!
This only works one way! For example, if I were to do AnyOf(2,3) == arr then my AnyOf class's __eq__ method never gets called: instead, the NumPy array's __eq__ method gets called, which internally (I would presume) calls the __eq__ method of all its elements.
This lead me to wonder: why does Python not allow a right-sided equivalent to __eq__? (Roughly equivalent to methods like __radd__, __rmul__, et cetera.)
An
__req__may have been considered more confusing than useful in the language. Consider if classLeftdefines__eq__and classRightdefines__req__, then Python is obliged to make a consistent decision about who gets called first inLeft() == Right()(and we would presumably like the result to be equivalent, either way). They can't both win.However, the Python datamodel does allow a way to do what you want here. The comparison can be controlled from either side of the operation, but you'll need to define
AnyOfin a particular way. To control the eq from the right hand side of a comparison when the left side is annp.ndarrayinstance,AnyOfshould be a subclass ofnp.ndarray.Actually, no, there's a fundamental misunderstanding evident here. The left side always gets first try at handling the equality comparison, unless the right side type is a subclass of the left side type.
In the comparison shown above, your custom
__eq__is being called, because the numpy array calls it! Sonp.ndarraywins, and it decides to check once per element. It literally could do anything else, including not calling yourAnyOf.__eq__at all.In the comparison shown above, your class does get the first try at the comparison, and it fails because of the way
inwas used -return other in self.elementsis checking if an array is in a tuple.