¿Son los objetos con el mismo id siempre iguales cuando los comparamos con ==?

Si tengo dos objetos o1 y o2, y sabemos que

id(o1) == id(o2) 

devuelve verdadero

Entonces, ¿sigue eso?

 o1 == o2 

¿O no es este siempre el caso? El documento en el que estoy trabajando dice que este no es el caso, pero en mi opinión, ¡debería ser cierto!

No siempre:

 >>> nan = float('nan') >>> nan is nan True 

o formulado de la misma manera que en la pregunta:

 >>> id(nan) == id(nan) True 

pero

 >>> nan == nan False 

NaN es una cosa extraña. Por definición no es igual ni menor ni mayor que la propia. Pero es el mismo objeto. Más detalles sobre por qué todas las comparaciones deben devolver False en esta pregunta de SO .

El papel es correcto. Considera lo siguiente.

 class WeirdEquals: def __eq__(self, other): return False w = WeirdEquals() print("id(w) == id(w)", id(w) == id(w)) print("w == w", w == w) 

La salida es esta:

 id(w) == id(w) True w == w False 

id(o1) == id(o2) no implica o1 == o2 .

Echemos un vistazo a este Troll que anula __eq__ para devolver siempre False .

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

Dicho esto, debería haber muy pocos ejemplos en la biblioteca estándar donde las identificaciones de los objetos coinciden, pero __eq__ puede devolver False todos modos, kudos @ MarkMüller por encontrar un buen ejemplo.

Entonces, ya sea que los objetos son demenciales, muy especiales (como nan), o la concurrencia te muerde. Considere este ejemplo extremo, donde Foo tiene un método __eq__ más razonable (que ‘se olvida’ de verificar los identificadores) y f is f siempre es 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() 

Salida:

 $ 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 ...