任何人都可以向我解释以下行为吗?NaNs作为词典的关键
>>> import numpy as np
>>> {np.nan: 5}[np.nan]
5
>>> {float64(np.nan): 5}[float64(np.nan)]
KeyError: nan
为什么它在第一种情况下工作,但不是在第二种情况下? 此外,我发现下列情况工作:
>>> a ={a: 5}[a]
float64(np.nan)
任何人都可以向我解释以下行为吗?NaNs作为词典的关键
>>> import numpy as np
>>> {np.nan: 5}[np.nan]
5
>>> {float64(np.nan): 5}[float64(np.nan)]
KeyError: nan
为什么它在第一种情况下工作,但不是在第二种情况下? 此外,我发现下列情况工作:
>>> a ={a: 5}[a]
float64(np.nan)
这里的问题是,NaN的不等于自身的根据IEEE标准定义的浮点数:
>>> float("nan") == float("nan")
False
当字典查找关键字,它大致这样做:
计算要查找的密钥的哈希值。
对于带相同散列的字典中的每个键,检查它是否与要查找的键匹配。此项检查包括:
a。检查对象标识:如果字典中的键和要查找的键与is
运算符指示的对象相同,则找到该键。
b。如果第一次检查失败,请使用__eq__
运算符检查相等性。
第一个例子成功,因为np.nan
和np.nan
是同一个对象,所以它并不重要都比不上等于:
>>> numpy.nan is numpy.nan
True
在第二种情况下,np.float64(np.nan)
和np.float64(np.nan)
不同一个对象 - 两个构造函数调用创建两个不同的对象:
>>> numpy.float64(numpy.nan) is numpy.float64(numpy.nan)
False
由于对象还会如果不相等,则字典结束该键未找到并抛出KeyError
。
你甚至可以做到这一点:
>>> a = float("nan")
>>> b = float("nan")
>>> {a: 1, b: 2}
{nan: 1, nan: 2}
总之,它似乎是一个理智的想法,以避免为NaN作为字典键。
请注意,这是不再在Python 3.6的情况下:
>>> d = float("nan")
>>> d
nan
>>> c = {"a": 3, d: 4}
>>> c["a"]
3
>>> c[d]
4
据我了解:
d =物体楠 c是相关联的,它包含一个字典3 “a” 和4与nan关联,但是,由于Python 3.6内部在字典中查找的方式发生了变化,现在它比较了两个指针,并且如果它们指向同一个对象,则认为它们保持相等。
这意味着,虽然:
>>> d == d
False
因为IEEE754是如何指定NAN不等于自己的,找了一本字典,当第一指针都考虑在内,因为它们指向同南对象返回4.
还要注意的是:
>>> e = float("nan")
>>> e == d
False
>>> c[e]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: nan
>>> c[d]
4
因此不是每个楠指向4,所以某种IEEE754的被保留。这是因为尊重nan不等于自身的标准会降低效率而不是忽视标准。正是因为你在字典中存储了一些你以前版本无法访问的东西。
这将永远是真的:'float('nan')!= float('nan')' – JBernardo