将 NaN 添加到集合时行为不一致的原因
Causes for inconsistent behavior when adding NaNs to a set
Python 的集合与 NaN
s (here live) 的组合有令人费解的(至少对我而言)行为:
>>> float('nan') in {float('nan')} # example 1
False
>>> nan = float('nan') # example 2
>>> nan in {nan}
True
起初,我错误地认为这是 ==
运算符的行为,但显然不是这种情况,因为这两种情况都会按预期产生 False
(here live):
>>> float('nan') == float('nan')
False
>>> nan = float('nan')
>>> nan == nan
False
我主要对这种行为的原因感兴趣。但是,如果有一种方法可以确保一致的行为,那也很高兴知道!
set membership 在考虑相等性检查之前进行身份检查作为短路(CPython 来源在 setobject.c
, see also the note below PyObject_RichCompareBool
)。
Python 核心开发人员受到这些不变量的激励:
for a in container:
assert a in container # this should ALWAYS be true
因此:
assert a in [a]
assert a in (a,)
assert a in {a}
决定确保这些不变量是最重要的优先事项,至于 NaN:哦,好吧。 特殊情况不足以违反规则。有关所有详细信息,请参阅 bpo issue4296:
Python assumes identity implies equivalence; contradicts NaN.
Python 的集合与 NaN
s (here live) 的组合有令人费解的(至少对我而言)行为:
>>> float('nan') in {float('nan')} # example 1
False
>>> nan = float('nan') # example 2
>>> nan in {nan}
True
起初,我错误地认为这是 ==
运算符的行为,但显然不是这种情况,因为这两种情况都会按预期产生 False
(here live):
>>> float('nan') == float('nan')
False
>>> nan = float('nan')
>>> nan == nan
False
我主要对这种行为的原因感兴趣。但是,如果有一种方法可以确保一致的行为,那也很高兴知道!
set membership 在考虑相等性检查之前进行身份检查作为短路(CPython 来源在 setobject.c
, see also the note below PyObject_RichCompareBool
)。
Python 核心开发人员受到这些不变量的激励:
for a in container:
assert a in container # this should ALWAYS be true
因此:
assert a in [a]
assert a in (a,)
assert a in {a}
决定确保这些不变量是最重要的优先事项,至于 NaN:哦,好吧。 特殊情况不足以违反规则。有关所有详细信息,请参阅 bpo issue4296:
Python assumes identity implies equivalence; contradicts NaN.