会员测试
float('nan') 的两个不同实例彼此不相等。它们是“不是数字”,因此它们不应该也必须相等是有道理的。它们是不是数字的对象的不同实例:
print(float('nan') == float('nan')) # False
据记录 here:
对于容器类型,例如 list、tuple、set、frozenset、dict 或
collections.deque, y 中的表达式 x 等价于 any(x is e
或 x == e for e in y)。
有一个身份检查!这就是为什么您在问题中看到这种行为以及为什么 NaN in a 返回 True 而 float('nan') in a 没有。
在 Python 中排序
Python 将Timsort 算法用于其sorted() 函数。 (另请参阅this 以获得文字解释。)我不打算深入讨论。我只是想演示一个简单的例子:
这是我的班级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 或这意味着 3 相对于 A(1) 处于正确位置。
- 然后这里
int.__lt__(4, A(1)) 被调用,因为它返回
NotImplemented 对象,Python 检查 A(1) 是否有
实现__gt__ 是的,所以A(1).__gt__(4) 将返回
False 再次,这意味着 A(1) 对象在正确的位置
相对于4。
- (等)
这就是为什么sorted() 的结果看起来很奇怪,但它是可以预测的。 A(1) 在这两种情况下都是对象,我的意思是当 int 类返回 NotImplemented 以及从 A(1) 调用 __lt__ 时,将返回 False。
最好检查Timsort 算法并考虑这些点。如果我仔细阅读 Timsort 算法,我会包括剩余的步骤。