将它们与==进行比较时,具有相同id的对象是否始终相等?

Jon*_*ann 59 python equality

如果我有两个对象o1和o2,我们就知道了

id(o1) == id(o2)
Run Code Online (Sandbox Code Playgroud)

返回true.

然后,它是否遵循这一点

o1 == o2
Run Code Online (Sandbox Code Playgroud)

或者情况并非如此?我正在研究的论文说情况并非如此,但在我看来应该是真的!

Mik*_*ler 129

不总是:

>>> nan = float('nan')
>>> nan is nan
True
Run Code Online (Sandbox Code Playgroud)

或以与问题中相同的方式制定:

>>> id(nan) == id(nan)
True
Run Code Online (Sandbox Code Playgroud)

>>> nan == nan
False
Run Code Online (Sandbox Code Playgroud)

NaN是一件奇怪的事情.根据定义,它不等于也不比自身更大或更大.但它是同一个对象.更多细节为什么所有比较都必须False这个SO问题中返回.

  • @JCLeitão - 这是因为接受的答案只是重新定义了`__eq__`以对某些特定类型的对象无意义地表现,但此处描述的行为存在于内置类型中.(对于声称符合IEEE754一致性的*所有*系统/语言,它也是相同的 - 等效的C代码执行*完全相同的事情*;) (28认同)
  • @AdamSmith:我认为这是一个比我更好的答案,希望我能想到它! (6认同)
  • @JCLeitão - Python*必须*允许它,否则你将无法创建实现IEEE754 NaN语义的BigFloat UDT.(例如,对于一组Python绑定到[MPFR库](http://www.mpfr.org/),这将是一个真正的拖累.) (3认同)
  • @JCLeitão - 根据您的问题的精神 - 这是您的用户期望提供类型的合同问题.对于依赖IEEE754精心设计的语义的科学用户而言,没有完全无序NaN的用户定义浮点类型将是非常令人惊讶的,而在表示解析器令牌的类中进行无反复比较同样令人惊讶.编译器编写者. (2认同)

rec*_*ive 58

这篇论文是对的.考虑以下.

class WeirdEquals:
    def __eq__(self, other):
        return False

w = WeirdEquals()
print("id(w) == id(w)", id(w) == id(w))
print("w == w", w == w)
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

id(w) == id(w) True
w == w False
Run Code Online (Sandbox Code Playgroud)


tim*_*geb 25

id(o1) == id(o2)并不意味着o1 == o2.

让我们来看看Troll__eq__总是返回的覆盖False.

>>> class Troll(object):
...     def __eq__(self, other):
...         return False
... 
>>> a = Troll()
>>> b = a
>>> id(a) == id(b)
True
>>> a == b
False
Run Code Online (Sandbox Code Playgroud)

话虽这么说,应该有在的对象ID匹配,但标准库的几个例子__eq__可以返回False反正荣誉@MarkMüller寻找一个很好的例子.

因此,无论是对象是疯狂的,非常特殊的(如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:
            f.x = 2
            f.x = 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()
Run Code Online (Sandbox Code Playgroud)

输出:

$ 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
...
Run Code Online (Sandbox Code Playgroud)