虽然myitem2有一个 NaN 值,但它是一个不同于 的float实例math.nan,因为+运算符总是返回一个新对象,即使它具有相同的值。
list2.count(nan)只返回列表中包含的次数math.nan。
它有助于查看对象 ID(示例值,每次运行代码时它们都不同):
>>> id(nan)
140305278866152
>>> id(myitem2)
140305278866176
>>> [id(x) for x in list2]
[9079008, 140305278866152, 140305278866152, 140305278866176]
# 1 nan nan myitem2
现在你可能会问,
>>> a = 5.0
>>> b = a + 0
>>> list3 = [a, b]
>>> id(a)
140133123191696
>>> id(b)
140133123191504
>>> [id(x) for x in list3]
[140133123191696, 140133123191504]
>>> list3.count(a)
2
为什么这不返回 1,因为a两个b不同的对象具有相同的值?
解释是,count实际上首先将每个列表项与它的参数按身份进行比较,但如果不同,则按值进行比较。
我没有找到指定的位置,但这里是 CPython实现(我添加的评论):
static PyObject *
list_count(PyListObject *self, PyObject *value)
{
Py_ssize_t count = 0;
Py_ssize_t i;
for (i = 0; i < Py_SIZE(self); i++) {
PyObject *obj = self->ob_item[i];
// comparison by identity
if (obj == value) {
count++;
continue;
}
Py_INCREF(obj);
// comparison by value
int cmp = PyObject_RichCompareBool(obj, value, Py_EQ);
Py_DECREF(obj);
if (cmp > 0)
count++;
else if (cmp < 0)
return NULL;
}
return PyLong_FromSsize_t(count);
}
最后,您需要知道按值将任何内容与 NaN 进行比较总是返回“不等于”,即使另一个值也是 NaN(我也没有找到为 Python 指定的位置,但请参阅Why does compare to nan yield False (Python)?以及对于 IEEE754 NaN 值返回 false 的所有比较的基本原理是什么?)。
这就是为什么myitem2不包含在 中.count(nan),而是b包含在 中的原因.count(a)。