You have a Python class which needs an equals test. Python should use duck-typing but is it (better/more accurate) to include or exclude an isinstance test in the eq function? For example:
class Trout(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(other, Trout) and self.value == other.value
Using
isintsance()
is usually fine in__eq__()
methods. You shouldn't returnFalse
immediately if theisinstance()
check fails, though -- it is better to returnNotImplemented
to giveother.__eq__()
a chance of being executed:This will become particularly important in class hierarchies where more than one class defines
__eq__()
:If you would return
False
immediately, as you did in your original code, you would lose symmetry betweenA(3) == B(3, 4)
andB(3, 4) == A(3)
.The "duck-typing" principle is that you don't care what
other
is, as long as it has avalue
attribute. So unless your attributes share names with conflicting semantics, I'd suggest doing it like this:(Alternately you could test whether
other
has avalue
attribute, but "it's easier to ask forgiveness than to get permission")Using isinstance in
__eq__
methods is pretty common. The reason for this is that if the__eq__
method fails, it can fallback on an__eq__
method from another object. Most normal methods are called explicitly, but__eq__
is called implicitly, so it requires look-before-you-leap more frequently.EDIT (thanks for the reminder, Sven Marnach):
To make it fallback, you can return the NotImplemented singleton, as in this example:
Suppose a
RainbowTrout
knows how to compare itself to aTrout
or to anotherRainbowTrout
, but aTrout
only knows how to compare itself to aTrout
. In this example, if you testmytrout == myrainbowtrout
, Python will first callmytrout.__eq__(myrainbowtrout)
, notice that it fails, and then callmyrainbowtrout.__eq__(mytrout)
, which succeeds.