代码之家  ›  专栏  ›  技术社区  ›  Ilya V. Schurov

在运算符中,浮点(“NaN”)和np。南安

  •  36
  • Ilya V. Schurov  · 技术社区  · 7 年前

    我曾经相信 in Python中的运算符使用相等检查检查某些集合中元素的存在情况 == 所以 element in some_list 大致相当于 any(x == element for x in some_list) . 例如:

    True in [1, 2, 3]
    # True because True == 1
    

    1 in [1., 2., 3.]
    # also True because 1 == 1.
    

    然而,众所周知 NaN 不等于自身。所以我预料到了 float("NaN") in [float("NaN")] False . 确实如此 错误 的确

    然而,如果我们使用 numpy.nan 而不是 float("NaN") ,情况完全不同:

    import numpy as np
    np.nan in [np.nan, 1, 2]
    # True
    

    但是 np.nan == np.nan 仍然提供 错误 !

    怎么可能呢?两者的区别是什么 np.nan 浮动(“NaN”) ? 如何 在里面 处理 np。南安 ?

    2 回复  |  直到 7 年前
        1
  •  35
  •   Alex Riley    7 年前

    为了检查该项是否在列表中,Python测试对象标识 第一 ,然后仅当对象不同时才测试相等性。 1.

    float("NaN") in [float("NaN")] 是错误的,因为两个 不同的 NaN 比较涉及对象。因此,标识测试返回False,然后相等测试也返回False,因为 NaN != NaN .

    np.nan in [np.nan, 1, 2] 然而,这是真的,因为 相同的 南安 比较涉及对象。对象标识测试返回True,因此Python会立即将该项识别为列表中的项。

    这个 __contains__ 方法(使用调用 in )对于许多Python的其他内置容器类型,如元组和集合,都是使用相同的检查来实现的。


    1. 至少在CPython是这样的。这里的对象标识意味着在相同的内存地址找到对象:即 contains method for lists 使用 PyObject_RichCompareBool 它可以在进行可能更复杂的对象比较之前快速比较对象指针。其他Python实现可能有所不同。

        2
  •  6
  •   Paul Panzer    7 年前

    值得一提的是,numpy数组的行为确实符合预期:

    a = np.array((np.nan,))
    a[0] in a
    # False
    

    主题变化:

    [np.nan]==[np.nan]
    # True
    [float('nan')]==[float('nan')]
    # False
    {np.nan: 0}[np.nan]
    # 0
    {float('nan'): 0}[float('nan')]
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # KeyError: nan
    

    其他一切都包含在@亚历克斯·赖利的精彩回答中。