与==相比,具有相同ID的对象是否总是相等?
如果我有两个对象o1和o2,我们知道
id(o1) == id(o2)
返回true 。
那么,它是否遵循这一点
o1 == o2
或者情况并非总是如此? 我正在研究的这篇论文说的不是这样,但是在我看来这应该是真的!
不总是:
>>> nan = float('nan') >>> nan is nan True
或者按照与问题中相同的方式制定:
>>> id(nan) == id(nan) True
但
>>> nan == nan False
NaN是一件奇怪的事情。 根据定义,它不等于或小于或大于自身。 但它是同一个对象。 更多细节为什么所有的比较都必须在这个SO问题中返回False
。
这篇文章是对的。 考虑以下。
class WeirdEquals: def __eq__(self, other): return False w = WeirdEquals() print("id(w) == id(w)", id(w) == id(w)) print("w == w", w == w)
输出是这样的:
id(w) == id(w) True w == w False
id(o1) == id(o2)
并不意味着o1 == o2
。
让我们来看看这个覆盖__eq__
总是返回False
Troll
。
>>> class Troll(object): ... def __eq__(self, other): ... return False ... >>> a = Troll() >>> b = a >>> id(a) == id(b) True >>> a == b False
也就是说,标准库中的object-id匹配的例子应该是非常less的,但是__eq__
无论如何都可以返回False
,Kudos @MarkMüllerfind了一个很好的例子。
因此,无论对象是疯了,非常特殊(如nan),或并发咬你。 考虑这个极端的例子, Foo
有一个更合理的__eq__
方法(忘记检查id), f is f
总是为True
。
import threading class Foo(object): def __init__(self): self.x = 1 def __eq__(self, other): return isinstance(other, Foo) and self.x == other.x f = Foo() class MutateThread(threading.Thread): def run(self): while True: fx = 2 fx = 1 class CheckThread(threading.Thread): def run(self): i = 1 while True: if not (f == f): print 'loop {0}: f != f'.format(i) i += 1 MutateThread().start() CheckThread().start()
输出:
$ python eqtest.py loop 520617: f != f loop 1556675: f != f loop 1714709: f != f loop 2436222: f != f loop 3210760: f != f loop 3772996: f != f loop 5610559: f != f loop 6065230: f != f loop 6287500: f != f ...