- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当我检查它是否存在于列表或集合中时,NaN 得到了完美的处理。但我不明白如何。 [更新:不,不是;如果找到相同的 NaN 实例,则报告为存在;如果仅发现不相同的 NaN 实例,则将其报告为不存在。]
我认为列表中的存在是通过相等性来检验的,所以我预计不会找到 NaN,因为 NaN != NaN。
hash(NaN) 和 hash(0) 都是 0。字典和集合如何区分 NaN 和 0?
使用 in
运算符检查任意容器中是否存在 NaN 是否安全?还是依赖于实现?
我的问题是关于 Python 3.2.1;但如果 future 版本中存在/计划进行任何更改,我也想知道。
NaN = float('nan')
print(NaN != NaN) # True
print(NaN == NaN) # False
list_ = (1, 2, NaN)
print(NaN in list_) # True; works fine but how?
set_ = {1, 2, NaN}
print(NaN in set_) # True; hash(NaN) is some fixed integer, so no surprise here
print(hash(0)) # 0
print(hash(NaN)) # 0
set_ = {1, 2, 0}
print(NaN in set_) # False; works fine, but how?
请注意,如果我将用户定义类的实例添加到 list
,然后检查是否包含,则调用实例的 __eq__
方法(如果已定义) - 至少在 CPython 中。这就是为什么我假设 list
包含是使用运算符 ==
测试的。
编辑:
根据 Roman 的回答,似乎 __contains__
用于 list
、tuple
、set
、 dict
的行为非常奇怪:
def __contains__(self, x):
for element in self:
if x is element:
return True
if x == element:
return True
return False
我说“奇怪”是因为我没有在文档中看到它的解释(也许我错过了),我认为这是不应该作为实现选择留下的东西。
当然,一个 NaN 对象可能与另一个 NaN 对象不同(在 id
的意义上)。 (这并不奇怪;Python 不保证这种身份。事实上,我从未见过 CPython 共享在不同地方创建的 NaN 实例,即使它共享一个小数字或短字符串的实例。)这意味着未定义在内置容器中测试是否存在 NaN。
这是非常危险的,而且非常微妙。有人可能会运行我上面显示的代码,并错误地得出结论认为使用 in
测试 NaN 成员资格是安全的。
我认为这个问题没有完美的解决方法。一种非常安全的方法是确保永远不会将 NaN 添加到内置容器中。 (在整个代码中检查这一点很痛苦……)
另一种选择是注意 in
左侧可能有 NaN 的情况,在这种情况下,使用 math.isnan()
单独测试 NaN 成员资格>。此外,还需要避免或重写其他操作(例如,设置交集)。
最佳答案
问题 #1:当容器是相同的对象时,为什么会在容器中找到 NaN。
来自documentation :
For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).
这正是我观察到的 NaN,所以一切都很好。为什么这个规则?我怀疑这是因为 dict
/set
想要诚实地报告它包含某个对象,如果该对象实际上在其中(即使 __eq__()
无论出于何种原因选择报告对象不等于自身)。
问题 #2:为什么 NaN 的哈希值与 0 的哈希值相同?
来自documentation :
Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict. hash() should return an integer. The only required property is that objects which compare equal have the same hash value; it is advised to somehow mix together (e.g. using exclusive or) the hash values for the components of the object that also play a part in comparison of objects.
注意只要求一个方向;具有相同哈希值的对象不必相等!起初我以为这是一个错字,但后来我意识到它不是。散列冲突无论如何都会发生,即使使用默认的 __hash__()
(请参阅出色的解释 here )。容器可以毫无问题地处理碰撞。当然,它们最终会使用 ==
运算符来比较元素,因此它们很容易以多个 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。
最后发现文档有误here :
For user-defined classes which do not define
__contains__()
but do define__iter__()
,x in y
is true if some valuez
withx == z
is produced while iterating overy
. If an exception is raised during the iteration, it is as ifin
raised that exception.Lastly, the old-style iteration protocol is tried: if a class defines
__getitem__()
,x in y
is true if and only if there is a non-negative integer indexi
such thatx == y[i]
, and all lower integer indices do not raiseIndexError
exception. (If any other exception is raised, it is as ifin
raised that exception).
您可能会注意到这里没有提到 is
,这与内置容器不同。我对此感到惊讶,所以我尝试了:
>>> nan1 = float('nan')
>>> nan2 = float('nan')
>>> class Cont:
... def __iter__(self):
... yield nan1
...
>>> c = Cont()
>>> nan1 in c
True
>>> nan2 in c
False
如您所见,首先检查身份,在 ==
之前 - 与内置容器一致。我将提交报告以修复文档。
关于python - 检查容器中是否存在 NaN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9904699/
首先我想说的是,我知道isNaN()和 Number.isNaN()工作。我正在阅读 David Flanagan 的 The Definite Guide,他举例说明了如何检查值是否为 NaN :
在表中,对于 skips day 列,最后一行的默认值始终是单词“last”,它不是数字。现在,结果日期显示为“NaN/NaN/NaN”,有什么方法可以将其替换为 Nil 之类的东西。 非常感谢。
我正在制作一个网站,如果用户登录,则会为用户提供一定的注销时间,其中定义了注销时间,剩余时间是从注销时间 - 服务器时间获得的。 我已经通过 PHP 获得了注销时间和服务器时间,但我想动态显示剩余时间
我有以下代码,它简单地初始化一个 UIImageView 以适应 UIImage 在当前屏幕尺寸上尽可能大的比例: CGSize mainScreenSize = [appDelegate mainS
这个问题已经有答案了: Why in numpy `nan == nan` is False while nan in [nan] is True? (1 个回答) 已关闭 3 年前。 我只是觉得这有
我有动态 JQGrid,其中一列是日期列。我从包含 URL 和日期的 feed 中获取数据。 我需要为“日期列”开发列模型,使其显示日期和超链接。但不幸的是,数据显示为 NAN/NAN/NAN (这可
我已经包含了一个演示我的问题的片段。基本上处理给了我这个错误: 调用map(NaN, -3, 3, -125, 125),返回NaN(不是数字) 我理解此消息的方式是,map 函数返回 NaN,并且由
我在下面创建的过滤器适用于 Chrome,但不适用于 Firefox。我不明白为什么。 myApp.filter('dateCustom', [ '$filter', function ($fil
虽然问题的第一部分(在标题中)之前已经回答过几次(即 Why is NaN not equal to NaN? ),但我不明白为什么第二部分会以它的方式工作(受此启发问题 How to Check l
我需要在数组中找到min和max值(不考虑可能的NaN值在这个数组中)。 这只使用 double 会很容易,但是这些 FindMin 和 FindMax 函数必须使用泛型类型。 我尝试以这种方式测
我正在开发一个屏幕,其中 UIScrollView 内只有一个 UIImageView。 UIScrollView 使用户能够固定和缩放图像。我从下面的帖子中得到了帮助。它使用 Storyboard和
尽管看到了类似的答案,但我不知道这里发生了什么。我制作了一个自定义的 UIImageview,它应该在创建后立即开始动画: class HeaderAnimator: UIImageView {
我正在寻找一个 pandas 系列并用下一个数值的平均值填充 NaN,其中:average = next numerical value/(# consecutive NaNs + 1) 到目前为止,
我有一个 mySql 表,其中有一个名为 posts 的列,该列设置为 timestamp 类型,默认为 current_timestamp。然后,我使用 php PDO 获取它的值(以及其他一些列)
我想知道以下类型的 nan 之间有什么区别。除了 NAN_macro (计算结果为 -nan(ind) 而不是 nan )的视觉差异外,它们的行为似乎都相同(根据下面的示例脚本)。 我看了一些其他的答
我为我的网页做了倒计时;它在除 Mozilla 和 IE 之外的所有浏览器上都能正常工作。 我做错了什么,我该如何解决? 下面是我的代码: ***var dt = '2018-06-14 11:59
在将 Xcode 更新到 8.3 后,我在启动时开始收到此错误:由于未捕获的异常“CALayerInvalidGeometry”而终止应用程序,原因:“CALayer 位置包含 NaN:[nan na
我正在使用 jquery 自动完成 onselect 它在不同的文本字段中显示数据。我使用 format_date() 函数在 #dob 和 #anniversery 中显示格式化日期 select:
我有一个带有 json Store 和 DateField 的网格。 Firefox 运行良好,但在 Internet Explorer 8 中无法运行。 我这样定义: function conver
我有一个错误,它在启动时使应用程序崩溃。这是我得到的错误: *** Terminating app due to uncaught exception 'CALayerInvalidGeometry'
我是一名优秀的程序员,十分优秀!