Comprender el operador "es" [duplicado]
El
is
operador no hace coincidir los valores de las variables, sino las instancias mismas.
que significa realmente?
Declaré dos variables nombradas x
y y
asignando los mismos valores en ambas variables, pero devuelve falso cuando uso el is
operador.
Necesito una aclaración. Aquí está mi código:
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # False
No entendiste lo que is
prueba el operador. Prueba si dos variables apuntan al mismo objeto , no si dos variables tienen el mismo valor.
De la documentación para el is
operador :
Los operadores
is
andis not
prueban la identidad del objeto:x is y
es verdadero si y solo six
yy
son el mismo objeto.
Utilice el ==
operador en su lugar:
print(x == y)
Esto imprime True
. x
y y
son dos listas separadas :
x[0] = 4
print(y) # prints [1, 2, 3]
print(x == y) # prints False
Si usa la id()
función, verá eso x
y y
tendrá diferentes identificadores:
>>> id(x)
4401064560
>>> id(y)
4401098192
pero si tuvieras que asignarlo, y
ambos x
apuntan al mismo objeto:
>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True
y is
muestra que ambos son el mismo objeto, devuelve True
.
Recuerde que en Python, los nombres son solo etiquetas que hacen referencia a valores ; puede tener varios nombres que apunten al mismo objeto. is
Le indica si dos nombres apuntan a un mismo objeto. ==
te dice si dos nombres se refieren a objetos que tienen el mismo valor.
Otro duplicado preguntaba por qué dos cadenas iguales generalmente no son idénticas, lo que en realidad no se responde aquí:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
Entonces, ¿por qué no son la misma cadena? Especialmente teniendo en cuenta esto:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
Dejemos un poco de lado la segunda parte. ¿Cómo podría ser cierto lo primero?
El intérprete tendría que tener una "tabla interna", una tabla que asigna valores de cadena a objetos de cadena, de modo que cada vez que intente crear una nueva cadena con el contenido 'abc'
, obtendrá el mismo objeto. Wikipedia tiene una discusión más detallada sobre cómo funcionan las prácticas.
Y Python tiene una tabla de internación de cadenas; puedes internar cadenas manualmente con el sys.intern
método.
De hecho, Python puede internar automáticamente cualquier tipo inmutable, pero no es obligatorio hacerlo. Diferentes implementaciones internarán diferentes valores.
CPython (la implementación que estás usando si no sabes qué implementación estás usando) interna automáticamente enteros pequeños y algunos singletons especiales como False
, pero no cadenas (ni enteros grandes, ni tuplas pequeñas, ni cualquier otra cosa). Puedes ver esto con bastante facilidad:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
Vale, pero ¿por qué eran z
idénticos w
?
Ese no es el intérprete que realiza automáticamente la pasantía, sino los valores plegables del compilador.
Si la misma cadena en tiempo de compilación aparece dos veces en el mismo módulo (es difícil definir qué significa exactamente esto; no es lo mismo que una cadena literal, porque r'abc'
, 'abc'
y 'a' 'b' 'c'
son literales diferentes pero la misma cadena), pero es fácil de entender intuitivamente), el compilador solo creará una instancia de la cadena, con dos referencias.
De hecho, el compilador puede ir aún más lejos: el optimizador 'ab' + 'c'
puede convertirlo 'abc'
, en cuyo caso se puede plegar junto con una 'abc'
constante en el mismo módulo.
Nuevamente, esto es algo que Python está permitido pero no es obligatorio. Pero en este caso, CPython siempre pliega cadenas pequeñas (y también, por ejemplo, pequeñas tuplas). (Aunque el compilador declaración por declaración del intérprete interactivo no ejecuta la misma optimización que el compilador módulo a la vez, no verá exactamente los mismos resultados de forma interactiva).
Entonces, ¿qué deberías hacer al respecto como programador?
Pues nada. Casi nunca tienes motivos para preocuparte si dos valores inmutables son idénticos. Si quieres saber cuándo puedes usar a is b
en lugar de a == b
, estás haciendo la pregunta equivocada. Úselo siempre a == b
excepto en dos casos:
- Para comparaciones más legibles con los valores singleton como
x is None
. - Para valores mutables, cuando necesite saber si la mutación
x
afectará el archivoy
.
is
sólo devuelve verdadero si en realidad son el mismo objeto. Si fueran iguales, un cambio en uno también se mostraría en el otro. He aquí un ejemplo de la diferencia.
>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]
Debido a una pregunta duplicada , esta analogía podría funcionar:
# - Darling, I want some pudding!
# - There is some in the fridge.
pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True
# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.
pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False