Entendiendo el operador “es” de Python

El operador is no coincide con los valores de las variables, sino con las instancias mismas.

que significa realmente?

Declaré dos variables llamadas y asignando los mismos valores en ambas variables, pero devuelve falso cuando uso el operador is .

Necesito una aclaración. Aquí está mi código.

 x = [1, 2, 3] y = [1, 2, 3] print x is y #It prints false! 

Usted malentendió lo que el operador prueba. Comprueba si dos variables apuntan al mismo objeto , no si dos variables tienen el mismo valor.

De la documentación para el operador is :

Los operadores is y is not prueban la identidad del objeto: x is y es verdadero si y solo si x e y son el mismo objeto.

Utilice el operador == lugar:

 print x == y 

Esto imprime True . x e y son dos listas separadas :

 x[0] = 4 print(y) # prints [1, 2, 3] print(x == y) # prints False 

Si usa la función id() verá que y tienen diferentes identificadores:

 >>> id(x) 4401064560 >>> id(y) 4401098192 

pero si tuviera que asignar y a x entonces ambos apuntan al mismo objeto:

 >>> x = y >>> id(x) 4401064560 >>> id(y) 4401064560 >>> x is y True 

y muestra que ambos son el mismo objeto, devuelve True .

Recuerde que en Python, los nombres son solo tags que hacen referencia a valores ; puede tener varios nombres que apuntan al mismo objeto. Te dice si dos nombres apuntan a un mismo objeto. == le dice si dos nombres se refieren a objetos que tienen el mismo valor.

Otro duplicado fue preguntar por qué dos cadenas iguales generalmente no son idénticas, lo que realmente 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 

Aplazemos un poco la segunda parte. ¿Cómo podría ser la primera verdad?

El intérprete tendría que tener una “tabla de internamiento”, una tabla que asigna valores de cadena a objetos de cadena, por lo que cada vez que intente crear una cadena nueva con el contenido 'abc' , obtendrá el mismo objeto. Wikipedia tiene una discusión más detallada sobre cómo funciona la internación.

Y Python tiene una tabla de interning de cadena; puede internar manualmente cadenas con el método sys.intern .

De hecho, Python puede internar automáticamente cualquier tipo inmutable, pero no está obligado a hacerlo. Diferentes implementaciones internarán diferentes valores.

CPython (la implementación que está utilizando si no sabe qué implementación está usando) integra automáticamente pequeños enteros y algunos singletons especiales como False , pero no cadenas (o enteros grandes, o tuplas pequeñas, o cualquier otra cosa). Puedes ver esto bastante fácilmente:

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

Está bien, pero ¿por qué z y w eran idénticos?

Ese no es el intérprete internamente, es el comstackdor de valores.

Si la misma cadena de tiempo de comstackción aparece dos veces en el mismo módulo (lo que significa exactamente esto es difícil de definir; no es lo mismo que una cadena literal, porque r'abc' , 'abc' y 'a' 'b' 'c' son todos literales diferentes pero la misma cadena, pero fácil de entender intuitivamente), el comstackdor solo creará una instancia de la cadena, con dos referencias.

De hecho, el comstackdor puede ir aún más lejos: 'ab' + 'c' puede ser convertido a 'abc' por el optimizador, en cuyo caso puede plegarse junto con una constante 'abc' en el mismo módulo.

Nuevamente, esto es algo que Python está permitido pero no se requiere que haga. Pero en este caso, CPython siempre pliega cadenas pequeñas (y también, por ejemplo, tuplas pequeñas). (Aunque el comstackdor del intérprete interactivo enunciado por sentencia no ejecuta la misma optimización que el comstackdor de módulo a la vez, por lo que no verá exactamente los mismos resultados interactivamente).


Entonces, ¿qué debes hacer al respecto como progtwigdor?

Pues nada. Casi nunca tiene motivos para preocuparse si dos valores inmutables son idénticos. Si desea saber cuándo puede usar a is b lugar de a == b , está haciendo la pregunta incorrecta. Siempre use a == b excepto en dos casos:

  • Para comparaciones más legibles a los valores singleton como x is None .
  • Para valores mutables, cuando necesita saber si la mutación de x afectará a la y .

solo devuelve true si en realidad son el mismo objeto. Si fueran iguales, un cambio a uno también se mostraría en el otro. Aquí hay 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] 

Preguntado por 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 

is y is not son los dos operadores de identidad en Python. is operador no compara los valores de las variables, sino que compara las identidades de las variables. Considera esto:

 >>> a = [1,2,3] >>> b = [1,2,3] >>> hex(id(a)) '0x1079b1440' >>> hex(id(b)) '0x107960878' >>> a is b False >>> a == b True >>> 

El ejemplo anterior muestra que la identidad (también puede ser la dirección de memoria en Cpython) es diferente para a y b (aunque sus valores son los mismos). Es por eso que cuando dices a is b devuelve falso debido a la falta de coincidencia en las identidades de ambos operandos. Sin embargo, cuando dice a == b , devuelve true porque la operación == solo verifica si ambos operandos tienen el mismo valor asignado.

Ejemplo interesante (para la nota extra):

 >>> del a >>> del b >>> a = 132 >>> b = 132 >>> hex(id(a)) '0x7faa2b609738' >>> hex(id(b)) '0x7faa2b609738' >>> a is b True >>> a == b True >>> 

En el ejemplo anterior, aunque a y b son dos variables diferentes, a is b devuelto True . Esto se debe a que el tipo de a es int que es un objeto inmutable. Entonces, Python (supongo que para guardar memoria) asignó el mismo objeto a b cuando se creó con el mismo valor. Entonces, en este caso, las identidades de las variables que coinciden y a is b resultan ser True .

Esto se aplicará a todos los objetos inmutables:

 >>> del a >>> del b >>> a = "asd" >>> b = "asd" >>> hex(id(a)) '0x1079b05a8' >>> hex(id(b)) '0x1079b05a8' >>> a is b True >>> a == b True >>> 

Espero que ayude.

Como puedes comprobar aquí a unos enteros pequeños. Los números por encima de 257 no son una pequeña sum, por lo que se calcula como un objeto diferente.

Es mejor utilizar == en este caso.

Más información está aquí: http://docs.python.org/2/c-api/int.html

x is y es igual que id(x) == id(y) , comparando la identidad de los objetos.

Como @tomász-kurgan señaló en el comentario a continuación, el operador se comporta inusualmente con ciertos objetos.

P.ej

 >>> class A(object): ... def foo(self): ... pass ... >>> a = A() >>> a.foo is a.foo False >>> id(a.foo) == id(a.foo) True 

Árbitro;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24

X apunta a una matriz, Y apunta a una matriz diferente. Esas matrices son idénticas, pero el operador es mirará esos punteros, que no son idénticos.

Compara la identidad del objeto, es decir, si las variables se refieren al mismo objeto en la memoria. Es como el == en Java o C (al comparar punteros).

Un ejemplo sencillo con frutas.

 fruitlist = [" apple ", " banana ", " cherry ", " durian "] newfruitlist = fruitlist verynewfruitlist = fruitlist [:] print ( fruitlist is newfruitlist ) print ( fruitlist is verynewfruitlist ) print ( newfruitlist is verynewfruitlist ) 

Salida:

 True False False 

Si intentas

 fruitlist = [" apple ", " banana ", " cherry ", " durian "] newfruitlist = fruitlist verynewfruitlist = fruitlist [:] print ( fruitlist == newfruitlist ) print ( fruitlist == verynewfruitlist ) print ( newfruitlist == verynewfruitlist ) 

La salida es diferente:

 True True True 

Esto se debe a que el operador == compara solo el contenido de la variable. Para comparar las identidades de 2 variables usa el operador is

Para imprimir el número de identificación:

 print ( id( variable ) )