Reputation: 3887
Say I have a Person class, with first, middle and last name attributes. I would like to be able to perform two different types of equality checks on Person objects:
I have been toying with the idea of using __eq__
and __ne__
separately for this:
Person('g', '', 'bluth') == Person('george', 'oscar', 'bluth') # False
Person('g', '', 'bluth') != Person('george', 'oscar', 'bluth') # False
It seems like a neat solution, but having !=
not always return the opposite of ==
makes me nervous though. Is it considered bad practice? Should I just steer clear of using the operators and just use a method like consistent(self, other)
?
Example implementation:
class Person(object):
def __init__(self, first, middle, last):
self.first = first
self.middle = middle
self.last = last
def __eq__(self, other):
if type(other) is type(self):
return self.__dict__ == other.__dict__
return NotImplemented
def __ne__(self, other):
if type(other) is type(self):
return not (self._compatible(self.first, other.first) and
self._compatible(self.middle, other.middle) and
self._compatible(self.last, other.last))
return NotImplemented
def _compatible(self, s, o):
if s and o:
if s == o or (len(s) == 1 and s == o[0]) or (len(o) == 1 and o == s[0]):
return True
return False
return True
Upvotes: 0
Views: 139
Reputation: 9132
Principle of least astonishment: make the inexact match be a named method, not an overloaded operator. Overloading ==
for exact match is okay, but overloading operators with semantics other than the obvious is likely to cause confusion. Is it terribly hard to type a few more characters and write Person("G. Bluth").could_be(Person("George Oscar Bluth"))
?
Upvotes: 5