2つのオブジェクト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 は奇妙なことです。定義によれば、それはそれ自体と同じでも、それ以下でも以下でもありません。しかし、それは同じオブジェクトです。 this SO question ですべての比較が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
を意味しません。
常にTroll
を返すように__eq__
をオーバーライドするこのFalse
を見てみましょう。
>>> class Troll(object):
... def __eq__(self, other):
... return False
...
>>> a = Troll()
>>> b = a
>>> id(a) == id(b)
True
>>> a == b
False
そうは言っても、標準ライブラリにはveryの例がいくつかあり、オブジェクト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()
出力:
$ 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
...