为什么(numpy.nan,1)==(numpy.nan,1)?

sat*_*oru 8 python

虽然numpy.nan不等于numpy.nan,但(float('nan'), 1)不等于float('nan', 1),

(numpy.nan, 1) == (numpy.nan, 1)
Run Code Online (Sandbox Code Playgroud)

可能是什么原因?Python首先检查id是否相同?如果在比较元组的项目时首先检查身份,那么为什么不直接比较对象时检查它?

Joã*_*tes 6

当你这样做numpy.nan == numpy.nan是numpy决定条件是否真实.当您比较tuplespython时,只是检查元组是否具有与它们相同的对象.您可以numpy通过转换tuples为numpy数组来做出决定.

np.array((1, numpy.nan)) == np.array((1,numpy.nan))
>>array([ True, False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

原因是当你==使用numpy对象时,你正在调用numpy函数__eq__(),该函数具体说明,nan != nan因为从数学角度讲它nan是不确定的(可能是任何东西)所以它是有意义的nan != nan.但是当你==使用元组时,你会调用__eq__()不关心数学的元组函数,只关心python对象是否相同.如果(float('nan'),1)==(float('nan'),1)它返回,False因为每次调用都会float('nan')在不同的地方分配内存,因为您可以通过执行检查float('nan') is float('nan').


sat*_*oru 3

当比较元组中的两个对象时,Python 首先检查它们是否相同。

注意numpy.nan is numpy.nan,但是float('nan') is not float('nan')。

在 中Objects/tupleobject.c,比较是这样进行的:

for (i = 0; i < vlen && i < wlen; i++) {
    int k = PyObject_RichCompareBool(vt->ob_item[i],
                                     wt->ob_item[i], Py_EQ);
    if (k < 0)
        return NULL;
    if (!k)
        break;
}
Run Code Online (Sandbox Code Playgroud)

在 中PyObject_RichCompareBool,您可以看到相等性检查:

if (v == w) {
    if (op == Py_EQ)
        return 1;
    else if (op == Py_NE)
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下示例验证这一点:

class A(object):
    def __eq__(self, other):
        print "Checking equality with __eq__"
        return True

a1 = A()
a2 = A()
Run Code Online (Sandbox Code Playgroud)

如果您尝试(a1, 1) == (a1, 1)不打印任何内容,(a1, 1) == (a2, 1)则将使用__eq__并打印我们的消息。

现在尝试a1 == a1看看它是否让你感到惊讶;P