¿Por qué la comparación de cadenas usando '==' o 'is' a veces produce un resultado diferente?

Resuelto jottos asked hace 14 años • 15 respuestas

Dos variables de cadena se establecen con el mismo valor. s1 == s2siempre regresa True, pero s1 is s2a veces regresaFalse .

Si abro mi intérprete de Python y hago la misma iscomparación, tiene éxito:

>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True

¿Por qué es esto?

jottos avatar Oct 01 '09 22:10 jottos
Aceptado

ises prueba de identidad y ==es prueba de igualdad. Lo que sucede en su código se emularía en el intérprete de esta manera:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

Entonces, no es de extrañar que no sean iguales, ¿verdad?

En otras palabras: a is bes el equivalente aid(a) == id(b)

SilentGhost avatar Oct 01 '2009 15:10 SilentGhost

Otras respuestas aquí son correctas: isse usa para comparar identidades== , mientras que se usa para comparar igualdad . Dado que lo que le importa es la igualdad (las dos cadenas deben contener los mismos caracteres), en este caso el isoperador simplemente está equivocado y debería utilizarlo ==en su lugar.

La razón por isla que funciona de forma interactiva es que (la mayoría) de las cadenas literales se internan de forma predeterminada. De Wikipedia:

Las cadenas internas aceleran las comparaciones de cadenas, que a veces son un cuello de botella en el rendimiento en aplicaciones (como compiladores y tiempos de ejecución de lenguajes de programación dinámicos) que dependen en gran medida de tablas hash con claves de cadena. Sin hacer prácticas, comprobar que dos cadenas diferentes son iguales implica examinar cada carácter de ambas cadenas. Esto es lento por varias razones: es inherentemente O(n) en la longitud de las cadenas; normalmente requiere lecturas de varias regiones de la memoria, lo que lleva tiempo; y las lecturas llenan el caché del procesador, lo que significa que hay menos caché disponible para otras necesidades. Con cadenas internas, una simple prueba de identidad del objeto es suficiente después de la operación interna original; Esto generalmente se implementa como una prueba de igualdad de punteros, normalmente solo una instrucción de máquina sin ninguna referencia a la memoria.

Entonces, cuando tiene dos cadenas literales (palabras que están literalmente escritas en el código fuente de su programa, entre comillas) en su programa que tienen el mismo valor, el compilador de Python internará automáticamente las cadenas, haciendo que ambas se almacenen al mismo tiempo. ubicación de la memoria. (Tenga en cuenta que esto no siempre sucede y las reglas para cuando esto sucede son bastante complicadas, así que no confíe en este comportamiento en el código de producción).

Dado que en su sesión interactiva ambas cadenas en realidad se almacenan en la misma ubicación de memoria, tienen la misma identidad , por lo que el isoperador funciona como se esperaba. Pero si construyes una cadena mediante algún otro método (incluso si esa cadena contiene exactamente los mismos caracteres), entonces la cadena puede ser igual , pero no es la misma cadena ; es decir, tiene una identidad diferente , porque es almacenado en un lugar diferente de la memoria.

Daniel Pryden avatar Oct 01 '2009 16:10 Daniel Pryden

La ispalabra clave es una prueba de identidad del objeto, mientras que ==es una comparación de valores.

Si usa is, el resultado será verdadero si y solo si el objeto es el mismo objeto. Sin embargo, ==será cierto siempre que los valores del objeto sean los mismos.

Thomas Owens avatar Oct 01 '2009 15:10 Thomas Owens