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.