为什么 NaN 在 python 中没有引发任何错误?



在我看来,像float('nan')这样的东西应该进行优化,但显然它们不在Python中。

>>> NaN = float('nan')
>>> a = [ 1, 2, 3, NaN ]
>>> NaN in a
True
>>> float('nan') in a
False

这与不像其他事情一样优化nan有什么意义吗?在我看来,nan只是nan

除此之外,当你在这些事情上使用sorted时,它们会产生奇怪的结果:

>>> sorted([3, nan, 4, 2, nan, 1])
[3, nan, 1, 2, 4, nan]

>>> 3 > float('nan')
False
>>> 3 < float('nan')
False

nan上的比较是这样定义的,但在我看来它并不"蟒蛇"。为什么它不会引起错误?

会员资格测试

CCD_ 7的两个不同实例彼此不相等。它们是";不是数字";因此,他们不应该也是平等的,这是有道理的。它们是非数字对象的不同实例:

print(float('nan') == float('nan'))  # False

如本文所述:

对于容器类型,如列表、元组、集合、frozenset、dict或collections.deque,y中的表达式x等价于任意表达式(x是e或x==e表示y中的e)。

有一个身份检查!这就是为什么您在问题中看到这种行为,以及为什么NaN in a返回Truefloat('nan') in a不返回。


Python中的排序

Python在其sorted()函数中使用了Timsort算法。(另请参阅此以获取文本解释。)我不打算详述。我只想演示一个简单的例子:

这是我的A班。它将成为我们的float('nan')对象。它的作用类似于float('nan'),因为它为所有比较操作返回False

class A:
def __init__(self, n):
self.n = n
def __lt__(self, other):
print(self, 'lt is calling', other)
return False
def __gt__(self, other):
print(self, 'gt is calling', other)
return False
def __repr__(self):
return f'A({self.n})'
class B:
def __init__(self, n):
self.n = n
def __lt__(self, other):
print(self, 'lt is calling', other)
return False
def __gt__(self, other):
print(self, 'gt is calling', other)
return False
def __repr__(self):
return f'B({self.n})'

当我们使用不带reverse=True参数的sorted()函数(或list.sort()方法)时,我们要求可迭代项按升序排序。为此,Python尝试依次调用__lt__方法,从列表中的第二个对象开始,查看它是否小于前一个对象,依此类推:

lst = [A(1), B(2), A(3), B(4)]
print(sorted(lst))

输出:

B(2) lt is calling A(1)
A(3) lt is calling B(2)
B(4) lt is calling A(3)
[A(1), B(2), A(3), B(4)]

现在,切换回您的示例:

lst = [3, A(1), 4, 2, A(1), 1]
print(sorted(lst))

输出:

A(1) lt is calling 3
A(1) gt is calling 4
A(1) gt is calling 2
A(1) lt is calling 2
A(1) lt is calling 4
A(1) gt is calling 1
[3, A(1), 1, 2, 4, A(1)]
  1. A(1).__lt__(3)将返回False。这意味着A(1)不小于大于3或这意味着CCD_ 24相对于CCD_
  2. 然后这里调用int.__lt__(4, A(1)),因为它返回NotImplemented对象,Python检查A(1)是否具有执行了__gt__,并且是,因此A(1).__gt__(4)将返回False,这意味着A(1)对象位于正确的位置相对于CCD_ 33
  3. (等)

这就是为什么sorted()的结果看起来很奇怪,但却是可以预测的。在这两种情况下,A(1)对象,我的意思是当int类返回NotImplemented时,以及当从A(1)调用__lt__时,返回False。

最好检查Timsort算法并考虑这些点。如果我仔细阅读Timsort算法,我会包括剩下的步骤。

相关内容

最新更新