2xB
2xB

Reputation: 296

How to call the default string equality function in Python?

I would assume:

import numpy as np
a = np.array(["a", "b", "c"])
print(a == "abc")
print("abc" == a)

to output

[False False False]
False

, because the latter comparison should use the definition of equality for strings and the former should use the definition of equality for NumPy arrays.

The real output is:

[False False False]
[False False False]

Why does this happen[1] and how would one prevent it[2]?

[1] I.e. why is str.__eq__ NotImplemented?

[2] I.e. how can one call the equality check that was performed if np.ndarray.__eq__ would not be implemented?

[Edit] This question was marked as possible duplicate to comparing a string 1-d numpy array elementwise, which it is not, because there the exact opposite is asked (basically how to use np.ndarray.__eq__), and neither [1] nor [2] are discussed at all.

Upvotes: 1

Views: 195

Answers (1)

Tomas Farias
Tomas Farias

Reputation: 1343

I'll give a quick rundown of what's happening:

The 'abc' == a expression will invoke 'abc'.__eq__(a) first, but str.__eq__ will return NotImplemented if passed an argument not of str type. As a fallback, Python will invoke a.__eq__('abc') instead. The reason behind delegating the comparison to the reflected method on the other object is because that object might actually implement it.

In this case, np.array.__eq__ can actually handle strings, by doing an element by element comparison, and returns [False, False, False]. As per the data model docs, this is accepted: __eq__ methods needn't return a bool value. This behavior will occur regardless of the position of the variables in the equality.

Now, to answer your questions specifically:

  • Why is str.__eq__ NotImplemented?

That's simply the expected behavior of str.__eq__, as the documentation states:

Objects of different types, except different numeric types, never compare equal

In other words, str.__eq__ is only implemented for str arguments. Comparing str types to other objects of different types would require some sort of implicit type conversion, which would go against the Zen of Python:

Explicit is better than implicit

  • How can one call the equality check that was performed if np.ndarray.__eq__ would not be implemented?

If both sides of the equality didn't implement __eq__, Python will do a final fallback to id(a) == id('abc') which will compare the addresses in memory of both objects. This will return just False as each id call will return an int, which will be different for each object. So, you could use id(a) == id('abc') if that's what you need.

Upvotes: 5

Related Questions