日期和时间不应相等
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))
期望的输出:
False
False
实际的输出:
True
False
为什么继承 datetime.date
会改变 __eq__
的结果呢?
1 个回答
5
在查看Python的源代码时,我们发现了一个关于 datetime.date.__eq__
的实现,这个实现是备用的。这里的定义并没有处理 datetime.date
对象和 datetime.datetime
对象之间的相等比较(顺序是这样的):
def __eq__(self, other):
if isinstance(other, date) and not isinstance(other, datetime):
return self._cmp(other) == 0
return NotImplemented
在一个例子中,结果是 False
,这里的 self
对象是 datetime.date
的实例,而不是 datetime.datetime
的实例(满足了 if
条件),所以它们会被比较,__eq__
就返回比较的结果。
同样,正如 @Abdul Niyas P M 提到的,通过查看 这个运算符的C语言实现(这是默认的实现),逻辑上是等价的,并且还包含了关于这种特定行为的注释:
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;
}
不过,返回 False
而不是 NotImplemented
这个事实又引出了另一个问题,但这可能与提问者在运行代码时使用的Python版本有关。
例如,3.12.2 版本的同一个方法的源代码(以及 C实现)并没有阻止在 other
是 datetime.datetime
时进行比较:
def __eq__(self, other):
if isinstance(other, date):
return self._cmp(other) == 0
return NotImplemented