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

2024-04-26 20:21:30 发布

您现在位置: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的比较是这样定义的,但在我看来它并不是“pythonic”。为什么它不会引起错误


Tags: infalsetrue定义错误nanfloatpythonic
1条回答
网友
1楼 · 发布于 2024-04-26 20:21:30

会员资格测试

float('nan')的两个不同实例彼此不相等。它们“不是一个数字”,所以它们也不必相等是有道理的。它们是非数字对象的不同实例:

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

如文件所述here

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 in a返回Truefloat('nan') in a不返回的原因


Python中的排序

Python将Timsort算法用于其sorted()函数。(另请参阅this了解文本解释。)我不打算讨论这个问题。我只想演示一个简单的示例:

这是我的班级。它将成为我们的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})'

当我们使用sorted()函数(或list.sort()方法)而不使用reverse=True参数时,我们要求按升序对iterable进行排序。为此,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或这意味着3相对于A(1)处于正确位置
  2. 然后在这里调用int.__lt__(4, A(1)),因为它返回 NotImplemented对象,Python检查A(1)是否有 已实现__gt__并且是,因此A(1).__gt__(4)将返回 False,这意味着A(1)对象位于正确的位置 相对于4
  3. (等)

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

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

相关问题 更多 >