日期和时间不应相等

8 投票
1 回答
254 浏览
提问于 2025-04-14 17:23
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实现)并没有阻止在 otherdatetime.datetime 时进行比较:

def __eq__(self, other):
    if isinstance(other, date):
        return self._cmp(other) == 0
    return NotImplemented

撰写回答