Python 当与==比较时,具有相同id的对象是否始终相等?

Python 当与==比较时,具有相同id的对象是否始终相等?,python,equality,Python,Equality,如果我有两个物体o1和o2,我们知道 id(o1) == id(o2) 返回真值 那么,是这样吗 o1 == o2 还是不总是这样?我正在写的报纸上说情况并非如此,但我认为这应该是真的 这篇文章是对的。请考虑以下内容: class WeirdEquals: def __eq__(self, other): return False w = WeirdEquals() print("id(w) == id(w)", id(w) == id(w)) print("w =

如果我有两个物体o1和o2,我们知道

id(o1) == id(o2)
返回真值

那么,是这样吗

o1 == o2

还是不总是这样?我正在写的报纸上说情况并非如此,但我认为这应该是真的

这篇文章是对的。请考虑以下内容:

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

让我们看一看这个
Troll
,它覆盖
\uuuu eq\uuu
始终返回
False

>>> class Troll(object):
...     def __eq__(self, other):
...         return False
... 
>>> a = Troll()
>>> b = a
>>> id(a) == id(b)
True
>>> a == b
False
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()
也就是说,在标准库中应该很少有对象ID匹配的示例,但是
\uuuuuueq\uuuuu
可以返回
False
,总之,对于找到一个好的示例,我们感到非常荣幸

所以要么对象是疯狂的,非常特殊的(比如nan),要么并发性会咬到你。考虑这个极端的例子,其中<代码> FoO 有一个更合理的< >代码>p>
>>> class Troll(object):
...     def __eq__(self, other):
...         return False
... 
>>> a = Troll()
>>> b = a
>>> id(a) == id(b)
True
>>> a == b
False
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()
输出:

$ 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
...
并非总是:

>>> nan = float('nan')
>>> nan is nan
True
或以与问题中相同的方式制定:

>>> id(nan) == id(nan)
True
但是


这是一件奇怪的事。根据定义,它不等于、不小于或大于自身。但它是同一个对象。更多详细信息,为什么所有比较都必须返回
False

@AdamSmith,为什么这比公认的答案更真实?@J.C.Leitão——这是因为公认的答案只是重新定义了
\uueq\uuuuu
,使其对某类对象表现出无意义的行为,但是这里描述的行为是以内置类型出现的。(对于所有声称符合IEEE754标准的系统/语言也是一样的——等效的C代码做了完全相同的事情;)@AdamSmith:我认为这是一个比我更好的答案,但愿我能想到它@J.C.Leitão——Python必须允许它,否则您将无法创建实现IEEE754 NaN语义的BigFloat UDT。(例如,这将是对Python绑定集的真正拖累。)@J.C.Leitão——不过,从你的问题的精神来看——这是你的用户期望该类型提供的契约的问题。对于依赖IEEE754精心编制的语义的科学用户来说,没有完全无序的NAN的用户定义的浮点类型是非常令人惊讶的,而在表示解析器令牌的类中进行不可伸缩的比较对于编译器编写者来说也同样令人惊讶。“事实并非如此,但我认为这应该是真的!“--请注意,“不是这样”和“应该是真的”并不是相互排斥的;-)人们应该将
=
操作符作为自反关系来实现,但在某些情况下,他们选择不这样做(
下面的怪数),在某些情况下,他们甚至找到了不这样做的理由,可能是由于外部约束(IEEE NaN)事实上,为了扩展上述内容,人们几乎肯定应该将
\uuuueq\uuuuuu
实现为一种等价关系(自反
断言a==a
,对称
如果a==b:assert b==a
,传递
如果a==b和b==c:assert a==c
).除了NaN和concurrency之外,
==
对于特定目的来说不是自反的还有哪些常见实例?@MartyMacGyver但vanilla Python没有这两种方法those@catnan实例的工作原理如下(导入数学后),我希望线程实例也能这样做,所以我不确定“香草”是什么意思“-我正在考虑将使用Python安装的默认软件包作为基线。我想问的是那些以及任何其他常见的软件包,它们都以这种特性而闻名。