¿Por qué la comparación de cadenas usando '==' o 'is' a veces produce un resultado diferente?
Dos variables de cadena se establecen con el mismo valor. s1 == s2
siempre regresa True
, pero s1 is s2
a veces regresaFalse
.
Si abro mi intérprete de Python y hago la misma is
comparación, tiene éxito:
>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True
¿Por qué es esto?
is
es 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 b
es el equivalente aid(a) == id(b)
Otras respuestas aquí son correctas: is
se 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 is
operador simplemente está equivocado y debería utilizarlo ==
en su lugar.
La razón por is
la 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 is
operador 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.
La is
palabra 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.