python reference equality semantics

== python



¿Hay alguna diferencia entre `==` y `is` en Python? (20)

¿Hay alguna diferencia entre == y is en Python?

Sí, tienen una diferencia muy importante.

== : verifica la igualdad - la semántica es que los objetos equivalentes (que no son necesariamente el mismo objeto) se probarán como iguales. Como dice la documentación :

Los operadores <,>, ==,> =, <= y! = Comparan los valores de dos objetos.

is : verifique la identidad: la semántica es que el objeto (como se mantiene en la memoria) es el objeto. Una vez más, la documentación dice :

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. La identidad del objeto se determina utilizando la función id() . x is not y produce el valor de verdad inverso.

Por lo tanto, la verificación de identidad es la misma que la verificación de la igualdad de los ID de los objetos. Es decir,

a is b

es lo mismo que:

id(a) == id(b)

donde id es la función incorporada que devuelve un entero que "se garantiza que es único entre los objetos que existen simultáneamente" (ver help(id) ) y donde a y b son objetos arbitrarios.

Otras direcciones de uso

Deberías usar estas comparaciones para su semántica. Se usa para verificar la identidad y == para verificar la igualdad.

PEP 8, la guía de estilo oficial de Python para la biblioteca estándar también menciona dos casos de uso para :

Las comparaciones con singletons como None deben hacerse siempre con o is not , nunca con los operadores de igualdad.

Además, tenga cuidado de escribir if x cuando realmente quiere decir if x is not None , por ejemplo, al probar si una variable o argumento que por defecto es None se estableció en algún otro valor. ¡El otro valor podría tener un tipo (como un contenedor) que podría ser falso en un contexto booleano!

Inferir la igualdad desde la identidad

Si is cierto, la igualdad generalmente se puede inferir - lógicamente, si un objeto es en sí mismo, entonces debería probarse como equivalente a sí mismo.

En la mayoría de los casos, esta lógica es cierta, pero se basa en la implementación del método especial __eq__ . Como dicen los doctores ,

El comportamiento predeterminado para la comparación de igualdad ( == y != ) Se basa en la identidad de los objetos. Por lo tanto, la comparación de igualdad de casos con la misma identidad resulta en igualdad, y la comparación de igualdad de casos con identidades diferentes resulta en desigualdad. Una motivación para este comportamiento predeterminado es el deseo de que todos los objetos sean reflexivos (es decir, x es y implica x == y).

y en aras de la coherencia, recomienda:

La comparación de la igualdad debe ser reflexiva. En otras palabras, los objetos idénticos deben ser iguales:

x is y implica x == y

Podemos ver que este es el comportamiento predeterminado para los objetos personalizados:

>>> class Object(object): pass >>> obj = Object() >>> obj2 = Object() >>> obj == obj, obj is obj (True, True) >>> obj == obj2, obj is obj2 (False, False)

El contrapositivo también suele ser cierto: si algo prueba no es igual, generalmente se puede inferir que no son el mismo objeto.

Dado que las pruebas de igualdad se pueden personalizar, esta inferencia no siempre es válida para todos los tipos.

Una excepción

Una excepción notable es nan : siempre prueba que no es igual a sí mismo:

>>> nan = float(''nan'') >>> nan nan >>> nan is nan True >>> nan == nan # !!!!! False

La verificación de la identidad puede ser mucho más rápida que la verificación de la igualdad (lo que puede requerir la verificación recursiva de los miembros).

Pero no puede sustituirse por igualdad en la que puede encontrar más de un objeto como equivalente.

Tenga en cuenta que al comparar la igualdad de listas y tuplas, se asumirá que la identidad de los objetos es igual (porque se trata de una verificación rápida). Esto puede crear contradicciones si la lógica es inconsistente, como lo es para nan :

>>> [nan] == [nan] True >>> (nan,) == (nan,) True

Un cuento cautelar:

La pregunta que intentamos usar is comparar enteros. No debe asumir que una instancia de un entero es la misma que una obtenida por otra referencia. Esta historia explica por qué.

Un comentarista tenía un código que se basaba en el hecho de que los enteros pequeños (de -5 a 256 inclusive) son singletons en Python, en lugar de verificar la igualdad.

Wow, esto puede llevar a algunos errores insidiosos. Tenía un código que verificaba si a es b, que funcionaba como yo quería porque a y b suelen ser números pequeños. El error solo ocurrió hoy, después de seis meses de producción, porque a y b finalmente fueron lo suficientemente grandes como para no ser almacenados en caché. - GWG

Funcionó en el desarrollo. Puede haber pasado algunas pruebas de unidad.

Y funcionó en producción, hasta que el código verificó un entero mayor que 256, momento en el cual falló en producción.

Este es un fallo de producción que podría haberse detectado en la revisión del código o posiblemente con un comprobador de estilo.

Permítanme enfatizar: no usar is comparar números enteros.

Mi Google-fu me ha fallado.

En Python, ¿son equivalentes las siguientes dos pruebas de igualdad?

n = 5 # Test one. if n == 5: print ''Yay!'' # Test two. if n is 5: print ''Yay!''

¿Esto es cierto para los objetos en los que compararía instancias (como dice una list )?

Bien, entonces este tipo de respuestas a mi pregunta:

L = [] L.append(1) if L == [1]: print ''Yay!'' # Holds true, but... if L is [1]: print ''Yay!'' # Doesn''t.

Entonces == prueba el valor ¿dónde is pruebas para ver si son el mismo objeto?


¿Cuál es la diferencia entre is y == ?

== y son diferentes comparaciones! Como ya han dicho otros:

  • == compara los valores de los objetos.
  • is compara las referencias de los objetos.

En Python, los nombres se refieren a objetos, por ejemplo, en este caso, value1 y value2 refieren a una instancia int almacena el valor 1000 :

value1 = 1000 value2 = value1

Debido a que value2 refiere al mismo objeto is y == dará True :

>>> value1 == value2 True >>> value1 is value2 True

En el siguiente ejemplo, los nombres value1 y value2 refieren a diferentes instancias int , incluso si ambos almacenan el mismo número entero:

>>> value1 = 1000 >>> value2 = 1000

Debido a que el mismo valor (entero) se almacena == será True , por eso a menudo se llama "comparación de valores". Sin embargo, devolverá False porque estos son objetos diferentes:

>>> value1 == value2 True >>> value1 is value2 False

¿Cuándo usar cuál?

Generalmente is una comparación mucho más rápida. Es por eso que CPython almacena en caché (o quizás reutilizar sería el mejor término) ciertos objetos como enteros pequeños, algunas cadenas, etc. Pero esto debe tratarse como un detalle de implementación que podría (incluso si es poco probable) cambiar en cualquier momento sin previo aviso.

Solo debes usar is si:

  • desea comprobar si dos objetos son realmente el mismo objeto (no solo el mismo "valor"). Un ejemplo puede ser si utiliza un objeto singleton como constante.
  • quiere comparar un valor a una constante de Python . Las constantes en Python son:

    • None
    • True 1
    • False 1
    • NotImplemented
    • Ellipsis
    • __debug__
    • clases (por ejemplo, int is int o int is float )
    • Podría haber constantes adicionales en módulos integrados o módulos de terceros. Por ejemplo, np.ma.masked desde el módulo NumPy)

En cualquier otro caso, debe usar == para verificar la igualdad.

¿Puedo personalizar el comportamiento?

Hay un aspecto para == que no se ha mencionado ya en las otras respuestas: es parte del "modelo de datos" de Pythons . Eso significa que su comportamiento se puede personalizar usando el método __eq__ . Por ejemplo:

class MyClass(object): def __init__(self, val): self._value = val def __eq__(self, other): print(''__eq__ method called'') try: return self._value == other._value except AttributeError: raise TypeError(''Cannot compare {0} to objects of type {1}'' .format(type(self), type(other)))

Este es solo un ejemplo artificial para ilustrar que el método realmente se llama:

>>> MyClass(10) == MyClass(10) __eq__ method called True

Tenga en cuenta que, de forma predeterminada (si no se puede encontrar otra implementación de __eq__ en la clase o en las superclases), __eq__ utiliza:

class AClass(object): def __init__(self, value): self._value = value >>> a = AClass(10) >>> b = AClass(10) >>> a == b False >>> a == a

Por lo tanto, es realmente importante implementar __eq__ si quiere "más" que solo una comparación de referencia para clases personalizadas.

Por otro lado no se pueden personalizar los cheques. Siempre se comparará solo si tienes la misma referencia.

¿Estas comparaciones siempre devolverán un valor booleano?

Debido a que __eq__ puede volver a implementarse o anularse, no se limita a devolver True o False . Podría devolver cualquier cosa (¡pero en la mayoría de los casos debería devolver un booleano!).

Por ejemplo, con matrices NumPy, el == devolverá una matriz:

>>> import numpy as np >>> np.arange(10) == 2 array([False, False, True, False, False, False, False, False, False, False], dtype=bool)

¡Pero si los cheques siempre regresarán True o False !

1 Como Aaron Hall mencionó en los comentarios:

Por lo general, no debe hacer ninguna. is True o is False , ya que uno normalmente usa estos "cheques" en un contexto que convierte implícitamente la condición en un booleano (por ejemplo, en una declaración if ). Así que hacer la comparación is True y el elenco booleano implícito está haciendo más trabajo que simplemente hacer el elenco booleano, y te limitas a los booleanos (lo que no se considera pitón).

Como menciona PEP8:

No compare los valores booleanos con True o False usando == .

Yes: if greeting: No: if greeting == True: Worse: if greeting is True:


"==" compara valores

"is" compara objetos subyacentes

# this pgm is to show you the diff b/n == and is # a==b and a is b # == compares values # is compares references i.e compares wether two variables refer to same object(memory) a=10 b=10 print(a==b) # returns True as a,b have same value 10 print(a is b) # returns True, # we usually falsey assume that a =10 a new object . b=10 a new obj created # but actually when b=10 ,nothing but b is pointed to 10 until value of a or b is changed from 10 a=[1] b=[1] print(a==b) #returns True as a,b have a list element 1 print(a is b) #returns False because here two different objs are created when initiated with lists


Como dijo John Feminella, la mayoría de las veces usarás == y! = Porque tu objetivo es comparar valores. Solo me gustaría categorizar lo que harías el resto del tiempo:

Hay una y solo una instancia de NoneType, es decir, None es un singleton. En consecuencia, foo == None y foo is None significan lo mismo. Sin embargo, la prueba es más rápida y la convención de Pythonic es usar foo is None .

Si está realizando una introspección o analizando con la recolección de basura o si está comprobando si su dispositivo de internado de cadenas personalizado está funcionando o no, entonces probablemente tenga un caso de uso para foo es bar .

Verdadero y Falso también son (ahora) singletons, pero no hay caso de uso para foo == True y ningún caso de uso para foo is True .


Como las otras personas en este post responden a la pregunta en detalle, enfatizaría principalmente la comparación entre is y == para cadenas que pueden dar resultados diferentes e instaría a los programadores a usarlas cuidadosamente.

Para la comparación de cadenas, asegúrese de usar == lugar de:

str = ''hello'' if (str is ''hello''): print (''str is hello'') if (str == ''hello''): print (''str == hello'')

Afuera:

str is hello str == hello

Pero en el siguiente ejemplo == y obtendremos diferentes resultados:

str = ''hello sam'' if (str is ''hello sam''): print (''str is hello sam'') if (str == ''hello sam''): print (''str == hello sam'')

Afuera:

str == hello sam

Conclusión:

El uso is cuidadosamente para comparar entre cuerdas.



El operador == compara los valores de ambos operandos y verifica la igualdad de valores. Mientras is operador verifica si ambos operandos se refieren al mismo objeto o no.

a = [1,2,3,4] b = a print(a == b) # true print(a is b) # true

Pero si lo hacemos

b = a[:] # b now references a copy of a print(a == b) # true print(a is b) # false print(a is not b) # true

Básicamente, is puede considerar como una abreviatura para id(a) == id(b) . Sin embargo, más allá de esto, hay peculiaridades del entorno de tiempo de ejecución que complican aún más las cosas. Las cadenas cortas y los enteros pequeños devolverán True cuando se compara con is , debido a que la máquina Python intenta usar menos memoria para objetos idénticos.

a = ''python'' b = ''python'' print(a == b) # true print(a is b) # true


En pocas palabras, is comprueba si dos referencias apuntan al mismo objeto o no. == comprueba si dos objetos tienen el mismo valor o no.

a=[1,2,3] b=a #a and b point to the same object c=list(a) #c points to different object if a==b: print(''#'') #output:# if a is b: print(''##'') #output:## if a==c: print(''###'') #output:## if a is c: print(''####'') #no output as c and a point to different object


En realidad, quería agregar esto como un comentario, pero no podría embellecerlo fácilmente, por lo tanto, agregando como respuesta, por favor no considere esto como una respuesta.

Esto es lo que hice para entender ...

Ejecute el seguimiento uno por uno y comprenda la salida en cada paso.

a = [1,2] b = [1,2,3] b.pop() id(a) id(b) a is b a == b


Hay una regla general para decirle cuándo usar == o is .

  • == es para la igualdad de valores . Úselo cuando desee saber si dos objetos tienen el mismo valor.
  • is para la igualdad de referencia . Úselo cuando desee saber si dos referencias se refieren al mismo objeto.

En general, cuando está comparando algo con un tipo simple, por lo general está comprobando la igualdad de valores , por lo que debe usar == . Por ejemplo, la intención de su ejemplo es probablemente comprobar si x tiene un valor igual a 2 ( == ), no si x se refiere literalmente al mismo objeto que 2.

Otra cosa a tener en cuenta: debido a la forma en que funciona la implementación de referencia de CPython, obtendrás resultados inesperados e inconsistentes si por error utilizas is comparar la igualdad de referencia en enteros:

>>> a = 500 >>> b = 500 >>> a == b True >>> a is b False

Eso es más o menos lo que esperábamos: b tienen el mismo valor, pero son entidades distintas. Pero ¿qué pasa con esto?

>>> c = 200 >>> d = 200 >>> c == d True >>> c is d True

Esto es inconsistente con el resultado anterior. ¿Que está pasando aqui? Resulta que la implementación de referencia de Python almacena en caché objetos enteros en el rango -5..256 como instancias singleton por razones de rendimiento. Aquí hay un ejemplo que demuestra esto:

>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i))); ... 250: True 251: True 252: True 253: True 254: True 255: True 256: True 257: False 258: False 259: False

Esta es otra razón obvia para no usar: el comportamiento se deja a las implementaciones cuando se usa erróneamente para la igualdad de valores.


La diferencia de Python entre es y es igual a (==)

El operador is puede parecer el mismo que el operador de igualdad, pero no son lo mismo.

Comprueba si ambas variables apuntan al mismo objeto, mientras que el signo == comprueba si los valores de las dos variables son iguales.

Entonces, si el operador devuelve True, entonces la igualdad es definitivamente True, pero lo contrario puede o no ser True.

Aquí hay un ejemplo para demostrar la similitud y la diferencia.

>>> a = b = [1,2,3] >>> c = [1,2,3] >>> a == b True >>> a == c True >>> a is b True >>> a is c False >>> a = [1,2,3] >>> b = [1,2] >>> a == b False >>> a is b False >>> del a[2] >>> a == b True >>> a is b False

Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.


La mayoría de ellos ya respondieron al punto. Solo como una nota adicional (basada en mi comprensión y experimentación pero no de una fuente documentada), la declaración

== si los objetos referidos por las variables son iguales

De las respuestas anteriores se debe leer como

== si los objetos a los que hacen referencia las variables son iguales y los objetos que pertenecen al mismo tipo / clase

. Llegué a esta conclusión basada en la siguiente prueba:

list1 = [1,2,3,4] tuple1 = (1,2,3,4) print(list1) print(tuple1) print(id(list1)) print(id(tuple1)) print(list1 == tuple1) print(list1 is tuple1)

Aquí el contenido de la lista y la tupla son iguales, pero el tipo / clase es diferente.


Sí, hay diferencia entre ambos.

  • ''=='' : compara objeto por valor.
  • ''en'' : compara el objeto por referencia.

    a = [1,2,3] b = a # both pointing to same object (memory location) a == b: True a in b: True #because a and b are pointing to same object

Ahora consideremos este caso:

a = [1,2,3] b = list(a) # creating copy of object a a == b: True # as values are same a in b: False # because they are pointing to different object.


Si bien todas estas respuestas que se basan en la implementación de la comparación de punteros de objeción frente a la comparación de valores son correctas, hay una razón sintáctica más profunda para determinar si un valor variable es None (en la lógica booleana a menudo representada como NULL ).

En la base de datos relacional y otros sistemas lógicos, NULL implica que el valor real es "desconocido". Por lo tanto, la expresión lógica xx == NULL siempre debe evaluarse como NULL , ya que es imposible saber si xx , cualquiera que sea el valor que tenga, es el mismo que el valor desconocido. En los lenguajes de programación que se adhieren más estrictamente a las reglas de la lógica booleana, xx == NULL (o Pythonically xx == None ) se evalúa correctamente como NULL , y deben proporcionarse medios alternativos para determinar si un valor de variable es NULL . Python es un valor atípico en este sentido, debido a la naturaleza unitaria de la referencia del objeto a None . Pero para mayor claridad y corrección lógica, usar el operador de comparación de Python is práctica mucho más sensata.


Son completamente diferentes . verifica la identidad del objeto, mientras que == verifica la igualdad (una noción que depende de los tipos de los dos operandos).

Es solo una coincidencia afortunada que " is " parece funcionar correctamente con enteros pequeños (por ejemplo, 5 == 4 + 1). Esto se debe a que CPython optimiza el almacenamiento de enteros en el rango (-5 a 256) al hacerlos singletons . Este comportamiento depende totalmente de la implementación y no se garantiza que se conserve en todo tipo de operaciones de transformación menores.

Por ejemplo, Python 3.5 también hace singletons de cadenas cortas, pero cortarlas interrumpe este comportamiento:

>>> "foo" + "bar" == "foobar" True >>> "foo" + "bar" is "foobar" True >>> "foo"[:] + "bar" == "foobar" True >>> "foo"[:] + "bar" is "foobar" False


Tu respuesta es correcta. El operador is compara la identidad de dos objetos. El operador == compara los valores de dos objetos.

La identidad de un objeto nunca cambia una vez que ha sido creado; usted puede pensar en ello como la dirección del objeto en la memoria.

Puede controlar el comportamiento de comparación de los valores de los objetos definiendo un método __cmp__ o un método de comparación enriquecido como __eq__ .


devolverá True si dos variables apuntan al mismo objeto, == si los objetos a los que hacen referencia las variables son iguales.

>>> a = [1, 2, 3] >>> b = a >>> b is a True >>> b == a True >>> b = a[:] >>> b is a False >>> b == a True

En su caso, la segunda prueba solo funciona porque Python almacena en caché pequeños objetos enteros, que es un detalle de implementación. Para enteros más grandes, esto no funciona:

>>> 1000 is 10**3 False >>> 1000 == 10**3 True

Lo mismo se aplica a los literales de cuerdas:

>>> "a" is "a" True >>> "aa" is "a" * 2 True >>> x = "a" >>> "aa" is x * 2 False >>> "aa" is intern(x*2) True

Por favor vea esta pregunta también.


https://docs.python.org/library/stdtypes.html#comparisons

Pruebas de identidad == Pruebas de igualdad.

Cada valor entero (pequeño) se asigna a un solo valor, por lo que cada 3 es idéntico e igual. Este es un detalle de implementación, aunque no es parte de la especificación de lenguaje


== determina si los valores son iguales, mientras is determina si son exactamente el mismo objeto e iguales.


o1 is o2 => compara si o1 y o2 apuntan a la misma ubicación física en la memoria (en otras palabras, si son el mismo objeto)

o1 == o2 => aquí python llama al método __cmp __ (o2) de o1, que idealmente debería comparar el valor y devolver True o False. (En otras palabras, compara valor)

Para las personas de Java:

  • En Java, para determinar si dos variables de cadena hacen referencia a la misma ubicación de memoria física utilizando str1 == str2 . (Llamada identidad de objeto, y se escribe en Python ya que str1 es str2 ).

  • Para comparar valores de cadena en Java, usestr1.equals (str2) ; en Python, use str1 == str2 .

Ejemplo:

class A(): ...: def __init__(self,a): ...: self.a = a ...: def __repr__(self): ...: return str(self.a) ...: def __cmp__(self, value): ...: print self.a ...: print value.a ...: return cmp(self.a, value.a)

Salida de Python Shell:

o = A (2) o1 = o

o == o1 2 2 Verdadero

o es o1 Verdadero

o1 = A (2)

o es o1 Falso