在我看来,像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
返回True
而float('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)]
A(1).__lt__(3)
将返回False
。这意味着A(1)
不小于大于3或这意味着CCD_ 24相对于CCD_- 然后这里调用
int.__lt__(4, A(1))
,因为它返回NotImplemented
对象,Python检查A(1)
是否具有执行了__gt__
,并且是,因此A(1).__gt__(4)
将返回False
,这意味着A(1)
对象位于正确的位置相对于CCD_ 33 - (等)
这就是为什么sorted()
的结果看起来很奇怪,但却是可以预测的。在这两种情况下,A(1)
对象,我的意思是当int
类返回NotImplemented
时,以及当从A(1)
调用__lt__
时,将返回False。
最好检查Timsort算法并考虑这些点。如果我仔细阅读Timsort算法,我会包括剩下的步骤。