from datetime import datetime, date
class MyDate(date):
pass
print(MyDate(2024, 3, 8) == datetime(2024, 3, 8))
print(date(2024, 3, 8) == datetime(2024, 3, 8))
Expected output:
False
False
Actual output:
True
False
Why does subclassing datetime.date change the __eq__ result?
Looking at the Python source code for datetime.date.__eq__ (the fallback implementation), we find the following definition, which does not implement an equality operator between a datetime.date object and a datetime.datetime object (in that order):
def __eq__(self, other):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) == 0
return NotImplemented
In the example where the result is False, the self object are instances of datetime.date, and are not instances of datetime.datetime (satisfying the if condition), so they get compared and __eq__ returns whatever the result of the comparison is.
Similarly, as noted by @Abdul Niyas P M, by looking at the C implementation of this operator (which is the default implementation), the definition is equivalent in logic, and further contains comments on this particular behavior:
static PyObject *
date_richcompare(PyObject *self, PyObject *other, int op)
{
/* Since DateTime is a subclass of Date, if the other object is
* a DateTime, it would compute an equality testing or an ordering
* based on the date part alone, and we don't want that.
* So return NotImplemented here in that case.
* If a subclass wants to change this, it's up to the subclass to do so.
* The behavior is the same as if Date and DateTime were independent
* classes.
*/
if (PyDate_Check(other) && !PyDateTime_Check(other)) {
int diff = memcmp(((PyDateTime_Date *)self)->data,
((PyDateTime_Date *)other)->data,
_PyDateTime_DATE_DATASIZE);
return diff_to_bool(diff, op);
}
else
Py_RETURN_NOTIMPLEMENTED;
}
However, the fact False is being returned instead of NotImplemented raises another question, but this could be due to the Python version the OP was using when running their code.
For instance, the 3.12.2 version source code of the same method (and C implementation) does not prevent the comparison when other is a datetime.datetime:
def __eq__(self, other):
if isinstance(other, date):
return self._cmp(other) == 0
return NotImplemented
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With