Using Python, I am trying to implement a set of types including a "don't care" type, for fuzzy matching. I have implemented it like so:
class Matchable(object):
def __init__(self, match_type = 'DEFAULT'):
self.match_type = match_type
def __eq__(self, other):
return (self.match_type == 'DONTCARE' or other.match_type == 'DONTCARE' \
or self.match_type == other.match_type)
Coming from an OO background, this solution seems inelegant; using the Matchable class results in ugly code. I'd prefer to eliminate match_type, and instead make each type its own class inherited from a superclass, then use type checking to do the comparisons. However type checking appears to be generally frowned upon:
http://www.canonical.org/~kragen/isinstance/
Is there are better (more pythonic) way to implement this functionality?
Note: I'm aware of the large number of questions and answers about Python "enums", and it may be that one of those answers is appropriate. The requirement for the overridden __ eq __ function complicates matters, and I haven't seen a way to use the proposed enum implementations for this case.
The best OO way I can come up with of doing this is:
class Match(object):
def __eq__(self, other):
return isinstance(self, DontCare) or isinstance(other, DontCare) or type(self) == type(other)
class DontCare(Match):
pass
class A(Match):
pass
class B(Match):
pass
d = DontCare()
a = A()
b = B()
print d == a
True
print a == d
True
print d == b
True
print a == b
False
print d == 1
True
print a == 1
False
The article you linked says that isinstance
isn't always evil, and I think in your case it is appropriate. The main complaint in the article is that using isinstance
to check whether an object supports a particular interface reduces opportunities to use implied interfaces, and it's a fair point. In your case, however, you would essentially be using a Dontcare
class to provide an annotation for how an object should be treated in comparisons, and isinstance
would be checking such an annotation, which should be perfectly. fine.