== python
¿Hay alguna diferencia entre `==` y `is` en Python? (20)
¿Hay alguna diferencia entre
==
yis
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
yis not
prueban la identidad del objeto:x is y
es verdadero si y solo six
ey
son el mismo objeto. La identidad del objeto se determina utilizando la funciónid()
.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 ois not
, nunca con los operadores de igualdad.Además, tenga cuidado de escribir
if x
cuando realmente quiere decirif x is not None
, por ejemplo, al probar si una variable o argumento que por defecto esNone
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
implicax == 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
oint 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
oFalse
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.
Eche un vistazo a la pregunta de desbordamiento de pila. El operador "is" de Python se comporta inesperadamente con los enteros .
En su mayor parte se reduce a que " is
" verifica si son el mismo objeto, no solo iguales entre sí (los números debajo de 256 son un caso especial).
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