Sacar la basura trae sus problemas
Esto no debería sorprenderte:
Después de todo, a y b son cosas distintas. Sin embargo:
Resulta que si uno usa literales, una de esas cosas no es como las demás.
Primero la explicación. Cuando uno no tiene más referencias a un dato, va a ser "garbage collected", la memoria se libera para que se pueda usar para otra cosa.
En el primer caso, las variables a y b guardan referencia a las listas. Es decir que tienen que existir todo el tiempo, ya que yo podría decir print a
y python tiene que poder responderme con el valor de a.
En el segundo caso, uso literales, lo que quiere decir que no hay referencias a las listas después de que se usan. Cuando python evalúa id([1,2]) == id([3,4])
evalúa primero el lado izquierdo del ==
. Después de que termina con eso, no hace falta mantener el [1,2]
a mano, así que se borra. Entonces, al evaluar el lado derecho, crea [3,4]
.
Por pura casualidad, lo pone en exactamente el mismo lugar en que estaba el [1,2]
, asi que id
devuelve el mismo valor. Esto sirve para recordar dos cosas:
a is b
es usualmente (pero no siempre) equivalente aid(a) == id(b)
La recolección de basura tiene efectos secundarios que en una de esas no esperabas.
Yes, but it's not pure chance - it's the result of object pooling in the implementation. If it were pure chance, the situation you describe would indeed be very rare.
Well, it's pure chance in that, for example, no other thread allocated the memory, and that python uses this specific memory allocation strategy. So, it's not pure chance that it happens this time, but it is pure chance that it happens at all.
It's worthy to note that this behaviour is an implementation detail: it's not enforced by the Python (the language) specification, so in other Python implementations (PyPy, Jython, IronPython) you may get different results.