TL;DR
It's because of how the comparison methods are defined.
Reason why `==` is comparable while `>=` isn't between `time` objects and type `int`:
Here's a copy of the source code for the time
object:
def __eq__(self, other):
if isinstance(other, time):
return self._cmp(other, allow_mixed=True) == 0
else:
return False
def __ge__(self, other):
if isinstance(other, time):
return self._cmp(other) >= 0
else:
_cmperror(self, other)
__eq__
returns False
when it's not another time
instance, while __ge__
calls _cmperror
, which is defined as followed:
def _cmperror(x, y):
raise TypeError("can't compare '%s' to '%s'" % (
type(x).__name__, type(y).__name__))
Very Important Edit
Although this answer already got some positive scores, but I have miss read your question, you used date
objects, not time
objects.
Reason why `==` is comparable while `>=` isn't between `date` objects and type `int`:
First of all, date
objects, unlike time
objects, they are implemented the same for __eq__
and __ge__
. Both of them actually returns NotImplemented
, therefore there's nothing special about the date
object's methods:
def __eq__(self, other):
if isinstance(other, date):
return self._cmp(other) == 0
return NotImplemented
def __ge__(self, other):
if isinstance(other, date):
return self._cmp(other) >= 0
return NotImplemented
What is different, however, is int
's __eq__
comparison's to the other methods. int
returns False
when an object has a none-comparable type for __eq__
and NotImplemented
for __ge__
.
The NotImplemented
returned by date
will result in a fallback on int
's methods. Since int
is always equality comparable, date == 0
does not result in an error.
Here is an example:
class LikeDate:
def __eq__(self, other):
if isinstance(other, LikeDate):
return True
else:
return NotImplemented
def __ge__(self, other):
if isinstance(other, LikeDate):
return True
else:
return NotImplemented
class LikeInt:
def __eq__(self, other):
if isinstance(other, LikeInt):
return True
else:
return False
def __ge__(self, other):
if isinstance(other, LikeInt):
return True
else:
return NotImplemented
a = LikeDate()
b = LikeInt()
print(a == b) # False
print(a == 0) # False, because int provides an __eq__ method that returns False
print(a >= 0) # Error, because nether LikeDate nor int provides a definite comparison for __ge__
print(a >= b) # Error, because neither objects provide a comparable __ge__
You can run this example here.
If you do not know what return NotImplemented
is, here's a short explanation and a quote from the doc:
When a binary [ ( __eq__
, __ge__
...) ] (or in-place) method returns NotImplemented
the
interpreter will try the reflected operation on the other type (or
some other fallback, depending on the operator). If all attempts
return NotImplemented
, the interpreter will raise an appropriate
exception. Incorrectly returning NotImplemented will result in a
misleading error message or the NotImplemented
value being returned to
Python code.
When NotImplemented
is returned from a binary method, it refers that the binary method isn't able to compare itself with the targets' type. The result of the binary method will depend on the other objects' binary method. If both object returns NotImplemented
an error is raised.