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!'
¿Es esto cierto para los objetos en los que compararía instancias (por list
ejemplo)?
De acuerdo, 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 ==
, ¿el valor de las pruebas donde las is
pruebas para ver si son el mismo objeto?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
salida:False True False
.b = a[:]
parte de copia de la lista del operador de división, así que edité tu respuesta para tener un comentario allí. Parece que acabo de llegar al umbral para no tener que revisar mis ediciones antes de que se apliquen, así que espero que sea genial para ti. De todos modos, aquí hay una referencia útil sobre cómo copiar listas que encontré y tuve que hacer referencia para averiguar qué estaba haciendo: stackoverflow.com/a/2612815/4561887==
. Entonces,5.0
por ejemplo, es un valor de coma flotante, mientras que5
es un número entero. Pero5.0 == 5
aún regresaráTrue
porque representan el mismo valor. En términos de rendimiento y tipificación de pato,is
el intérprete siempre prueba al comparar las direcciones de memoria del operando, mientras==
que depende del objeto decidir si se define como igual a otra cosa.1000 is 10**3
se evalúa como Verdadero en Python 3.7 ya que 10 ** 3 es tipoint
. Pero se1000 is 1e3
evalúa como False ya que 1e3 es typefloat
.1000 is 10**3
verdad es o no depende de la implementación y depende de que el compilador evalúe previamente la expresión10**3
.x=10; 1000 is x**3
evalúa aFalse
.Hay una regla general simple que le indica cuándo usar
==
ois
.==
es por la igualdad de valores . Úselo cuando desee saber si dos objetos tienen el mismo valor.is
es para referencia de igualdad . Úselo cuando desee saber si dos referencias se refieren al mismo objeto.En general, cuando compara algo con un tipo simple, generalmente verifica la igualdad de valor , por lo que debe usar
==
. Por ejemplo, la intención de su ejemplo es probablemente verificar si x tiene un valor igual a 2 (==
), no six
se refiere literalmente al mismo objeto que 2.Algo más a tener en cuenta: debido a la forma en que funciona la implementación de referencia de CPython, obtendrá resultados inesperados e inconsistentes si usa por error
is
para comparar la igualdad de referencia en enteros:Eso es más o menos lo que esperábamos:
a
yb
tienen el mismo valor, pero son entidades distintas. ¿Pero qué hay de esto?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:
Esta es otra razón obvia para no usar
is
: el comportamiento se deja a las implementaciones cuando se usa erróneamente para la igualdad de valores.fuente
a=500
yb=500
, solo quería señalar que si establecea
yb
un número entero entre [-5, 256], ena is b
realidad regresaTrue
. Más información aquí: stackoverflow.com/q/306313/7571052==
determina si los valores son iguales, mientras queis
determina si son exactamente el mismo objeto.fuente
Sí, tienen una diferencia muy importante.
==
: verifique la igualdad: la semántica es que los objetos equivalentes (que no son necesariamente el mismo objeto) probarán como iguales. Como dice la documentación :is
: verifique la identidad: la semántica es que el objeto (como se mantiene en la memoria) es el objeto. De nuevo, la documentación dice :Por lo tanto, verificar la identidad es lo mismo que verificar la igualdad de las ID de los objetos. Es decir,
es lo mismo que:
¿Dónde
id
está la función incorporada que devuelve un número entero que "se garantiza que es único entre los objetos existentes simultáneamente" (verhelp(id)
) y dóndea
yb
cualquier objeto arbitrario.Otras direcciones de uso
Debe usar estas comparaciones para su semántica. Use
is
para verificar la identidad y==
para verificar la igualdad.Entonces, en general, usamos
is
para verificar la identidad. Esto suele ser útil cuando buscamos un objeto que solo debería existir una vez en la memoria, denominado "singleton" en la documentación.Los casos de uso para
is
incluyen:None
Los casos de uso habituales para
==
incluyen:El caso de uso general, nuevamente, para
==
, es que el objeto que desea puede no ser el mismo objeto, sino que puede ser uno equivalentePEP 8 direcciones
PEP 8, la guía de estilo oficial de Python para la biblioteca estándar también menciona dos casos de uso para
is
:Inferir igualdad de identidad
Si
is
es cierto, la igualdad generalmente se puede inferir: lógicamente, si un objeto es él 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
__eq__
método especial. Como dicen los documentos ,y en aras de la coherencia, recomienda:
Podemos ver que este es el comportamiento predeterminado para los objetos personalizados:
El contrapositivo también suele ser cierto: si algo prueba que 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:Verificar la identidad puede ser una verificación mucho más rápida que verificar la igualdad (lo que puede requerir la verificación recursiva de los miembros).
Pero no puede ser sustituido por igualdad donde puede encontrar más de un objeto como equivalente.
Tenga en cuenta que al comparar la igualdad de listas y tuplas se supondrá que la identidad de los objetos es igual (porque esta es una comprobación rápida). Esto puede crear contradicciones si la lógica es inconsistente, como lo es para
nan
:Un cuento de precaución:
La pregunta está intentando usar
is
para comparar enteros. No debe suponer que una instancia de un entero es la misma instancia 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 (-5 a 256 inclusive) son singletons en Python, en lugar de verificar la igualdad.
Funcionó en desarrollo. Puede haber pasado algunas pruebas unitarias.
Y funcionó en producción, hasta que el código verificó un número entero mayor que 256, momento en el cual falló en producción.
Esta es una falla de producción que podría haberse detectado en la revisión del código o posiblemente con un verificador de estilo.
Permítanme enfatizar: no lo use
is
para comparar enteros.fuente
is None
es una excepción, pero eso== None
también funciona ...is
para compararEnum
s.¿Cuál es la diferencia entre
is
y==
?==
yis
son diferentes comparaciones! Como otros ya dijeron:==
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 sevalue2
refieren a unaint
instancia que almacena el valor1000
:Porque se
value2
refiere al mismo objetois
y==
daráTrue
:En el siguiente ejemplo, los nombres
value1
y sevalue2
refieren a diferentesint
instancias, incluso si ambos almacenan el mismo número entero:Debido a que el mismo valor (entero) se almacena
==
seráTrue
, por eso a menudo se denomina "valor de comparación". Sin embargois
, regresaráFalse
porque estos son objetos diferentes:¿Cuándo usar cuál?
Generalmente
is
es una comparación mucho más rápida. Es por eso que CPython almacena en caché (o quizás reutilizaciones 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 debe usar
is
si usted:desea comparar un valor con una constante de Python . Las constantes en Python son:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
oint is float
)np.ma.masked
del módulo NumPy)En cualquier otro caso, debe usar
==
para verificar la igualdad.¿Puedo personalizar el comportamiento?
Hay algún aspecto
==
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 utilizando el__eq__
método. Por ejemplo:Este es solo un ejemplo artificial para ilustrar que el método realmente se llama:
Tenga en cuenta que por defecto (si no
__eq__
se puede encontrar otra implementación de la clase o las superclases)__eq__
utilizais
:Por lo tanto, es importante implementarlo
__eq__
si desea "más" que solo una comparación de referencia para clases personalizadas.Por otro lado, no puede personalizar los
is
cheques. Siempre se comparará solo si tiene la misma referencia.¿Estas comparaciones siempre devolverán un valor booleano?
Debido a que
__eq__
se puede volver a implementar o anular, no se limita a returnTrue
oFalse
. Se podría devolver nada (pero en la mayoría de los casos se debe devolver un valor lógico!).Por ejemplo, con matrices NumPy
==
, devolverá una matriz:¡Pero los
is
cheques siempre volveránTrue
oFalse
!1 Como Aaron Hall mencionó en los comentarios:
En general, no debe hacer ninguna
is True
ois False
verificaciones porque normalmente se usan estas "verificaciones" en un contexto que convierte implícitamente la condición a un valor booleano (por ejemplo, en unaif
declaración). Entonces, hacer lais True
comparación y el elenco booleano implícito está haciendo más trabajo que solo hacer el elenco booleano, y se limita a los booleanos (que no se considera pitónico).Como PEP8 menciona:
fuente
is
: los nombres que apuntan a booleanos deben verificarse con un contexto booleano, comoif __debug__:
oif not __debug__:
. Nunca debe hacerif __debug__ is True:
oif __debug__ == True:
, además, una constante es simplemente un valor semántico constante, no un singleton, por lo tanto, verificaris
en ese caso no es semánticamente correcto. Te reto a que encuentres una fuente que respalde tus afirmaciones; no creo que encuentres una.None
,True
,False
y__debug__
son lo que se llama "valor semántico constante", porque no pueden ser reasignados. Pero todos ellos son solteros.is True
oif False
check (pero sí, estos son bastante raros, pero si los haces puedes usarlosis
). Es por eso que incluso CPython los usa a veces (por ejemplo aquí o aquí )Son completamente diferentes .
is
comprueba la identidad del objeto, mientras que==
comprueba 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 únicos . Este comportamiento depende totalmente de la implementación y no se garantiza su preservación en todo tipo de operaciones de transformación menores.Por ejemplo, Python 3.5 también crea cadenas cortas simples, pero cortarlas interrumpe este comportamiento:
fuente
https://docs.python.org/library/stdtypes.html#comparisons
is
pruebas de identidad==
pruebas de igualdadCada 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 forma parte de la especificación del lenguaje
fuente
Tu respuesta es correcta. El
is
operador compara la identidad de dos objetos. El==
operador compara los valores de dos objetos.La identidad de un objeto nunca cambia una vez que se ha creado; 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
__cmp__
método o un método de comparación rico como__eq__
.fuente
Eche un vistazo a la pregunta de desbordamiento de pila El operador "es" de Python se comporta inesperadamente con los enteros .
En general, se reduce a que "
is
" verifica si son el mismo objeto, no solo iguales entre sí (los números por debajo de 256 son un caso especial).fuente
En pocas palabras,
is
comprueba si dos referencias apuntan al mismo objeto o no.==
comprueba si dos objetos tienen el mismo valor o no.fuente
Como dijo John Feminella, la mayoría de las veces usará == y! = Porque su objetivo es comparar valores. Solo me gustaría clasificar lo que harías el resto del tiempo:
Hay una única instancia de NoneType, es decir, None es un singleton. En consecuencia
foo == None
yfoo is None
significa lo mismo. Sin embargo, lais
prueba es más rápida y se debe usar la convención Pythonicfoo is None
.Si usted está haciendo un poco de introspección o curioseaba con la recolección de basura o la comprobación de si la cadena hecha a la medida internar aparato funciona o cosas por el estilo, entonces es probable que tenga un caso de uso para el
foo
que esbar
.True y False también son (ahora) singletons, pero no hay un caso de
foo == True
uso ni un caso de uso parafoo is True
.fuente
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
de las respuestas anteriores deben leerse como
. Llegué a esta conclusión en base a la prueba a continuación:
Aquí el contenido de la lista y la tupla son los mismos, pero el tipo / clase es diferente.
fuente
La diferencia de Python entre es y es igual (==)
Aquí hay un ejemplo para demostrar la similitud y la diferencia.
fuente
A medida que las otras personas en esta publicación responden a la pregunta en detalle, enfatizaría principalmente la comparación entre
is
y==
para cadenas que pueden dar diferentes resultados e instaría a los programadores a usarlas cuidadosamente.Para la comparación de cadenas, asegúrese de usar en
==
lugar deis
:Fuera:
Pero en el siguiente ejemplo
==
yis
obtendremos resultados diferentes:Fuera:
Conclusión:
Use con
is
cuidado para comparar entre cadenasfuente