检查容器中是否存在NaN

检查容器中是否存在NaN,第1张

检查容器中是否存在NaN

问题#1:为什么在同一对象中的容器中会发现NaN。

文档中:

对于列表,元组,集合,frozenset,dict或collections.deque等容器类型,y中的表达式x等于any(x为e或y中的e为x ==
e)。

这正是我在NaN上观察到的,所以一切都很好。为什么要这个规则?我怀疑这是因为

dict
/
set
想要诚实地报告它包含某个对象(如果该对象确实存在于其中)(即使
__eq__()
出于某种原因选择报告该对象不等于自身)。

问题2:为什么NaN的哈希值与0相同?

从文档中:

由内置函数hash()调用,用于对散列集合的成员(包括set,frozenset和dict)进行 *** 作。 hash
()应该返回一个整数。唯一需要的属性是比较相等的对象具有相同的哈希值;建议以某种方式将散列值混合在一起(例如,使用异或),以将对象的组成部分也用作对象比较的一部分。

请注意,此要求仅在一个方向上进行;具有相同散列的对象不必相等!起初我以为是错字,但后来我意识到不是。哈希冲突无论如何都会发生,即使默认情况下也是如此

__hash__()
(请参阅此处的出色说明)。容器可以毫无问题地处理碰撞。当然,它们确实最终会使用
==
运算符来比较元素,因此,只要它们不相同,它们很容易以多个NaN值结束!尝试这个:

>>> nan1 = float('nan')>>> nan2 = float('nan')>>> d = {}>>> d[nan1] = 1>>> d[nan2] = 2>>> d[nan1]1>>> d[nan2]2

因此,一切工作均按文档记录。但是…非常非常危险!有多少人知道NaN的多种价值可以在一个命令中彼此并存?有多少人会觉得这很容易调试?

我建议将NaN设为

float
不支持哈希的子类的实例,因此不能意外地将其添加到
set
/中
dict
。我将其提交给python-ideas。

最后,我在这里的文档中发现了一个错误:

对于不定义用户定义的类

__contains__()
,但不限定
__iter__()
x in y
如果一些值为true
z
x ==z
同时迭代产生
y
。如果在迭代过程中
in
引发了异常,则好像引发了该异常。

最后,尝试使用旧式的迭代协议:如果一个类定义

__getitem__()
x in y
则当且仅当存在一个非负整数索引(
i
例如)
x ==y[i]
,并且所有较低的整数索引都不会引发
IndexError
异常时,该方法才为true
。(如果引发了其他任何异常,则好像
in
引发了该异常)。

您可能会注意到,

is
与内置容器不同,这里没有提及。我对此感到惊讶,因此我尝试:

>>> nan1 = float('nan')>>> nan2 = float('nan')>>> class Cont:...   def __iter__(self):...     yield nan1...>>> c = Cont()>>> nan1 in cTrue>>> nan2 in cFalse

如您所见,先检查身份,然后再检查

==
-与内置容器一致。我将提交报告以修复文档。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5647721.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存