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


Mi Google-fu me ha fallado

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

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

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

¿Es esto cierto para objetos en los que estaría comparando instancias (un list decir)?

De acuerdo, 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.

Asi que == prueba valor donde is pruebas para ver si son el mismo objeto?


516
2017-09-25 12:27


origen


Respuestas:


is regresará True si dos variables apuntan al mismo objeto, == si los objetos referidos por 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 es cierto para los literales de cadena:

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

Por favor mira esta pregunta también.


713
2017-09-25 12:32



Hay una simple regla de oro para decirle cuándo usar == o is.

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

En general, cuando comparas algo con un tipo simple, generalmente estás buscando igualdad de valor, entonces deberías usar ==. Por ejemplo, la intención de su ejemplo es probablemente verificar si x tiene un valor igual a 2 (==), no si x se está refiriendo 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 CPython, obtendrás resultados inesperados e incoherentes si utilizas por error is para comparar para 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: a y b tienen el mismo valor, pero son entidades distintas. Pero, ¿qué hay de 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 únicas por motivos 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 is: el comportamiento queda en manos de las implementaciones cuando lo usa erróneamente para la igualdad de valores.


229
2017-07-06 06:22



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


22
2017-09-25 12:31



Son completamente diferente. is comprueba la identidad del objeto, mientras == 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). Eso es porque CPython optimiza el almacenamiento de enteros en el rango (-5 a 256) convirtiéndolos en singletons. Este comportamiento es totalmente dependiente de la implementación y no se garantiza que se preserve bajo todo tipo de operaciones transformativas menores.

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

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

12
2017-09-25 17:15



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

Sí, tienen una diferencia muy importante.

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

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

is: verificar identidad - la semántica es que el objeto (como se guarda en la memoria) es el objeto. Nuevamente, el la documentación dice:

Los operadores is y is not prueba de identidad de objeto: x is y es verdad   si y solo si x y y son el mismo objeto La identidad del objeto es   determinado usando el id() función. x is not y cede el inverso   valor de verdad.

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

a is b

es lo mismo que:

id(a) == id(b)

dónde id es la función integrada que devuelve un número entero que "se garantiza que es único entre los objetos existentes simultáneamente" (ver help(id)) y donde a y b son cualquier objeto arbitrario

Otras direcciones de uso

Debe usar estas comparaciones para su semántica. Utilizar is 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 is:

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

Además, ten cuidado con la escritura if x cuando realmente quieres decir if x is not None -   p.ej. al probar si una variable o argumento que se predetermina a None   se estableció en algún otro valor. El otro valor puede tener un tipo (tal   como contenedor) que podría ser falso en un contexto booleano.

Inferir igualdad de identidad

Si is es cierto, la igualdad puede generalmente inferirse: lógicamente, si un objeto es en sí mismo, debe 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 de __eq__ método especial. Como el documentos decir,

El comportamiento predeterminado para la comparación de igualdad (== y !=) está basado en   la identidad de los objetos. Por lo tanto, comparación de igualdad de instancias   con la misma identidad resulta en igualdad, y comparación de igualdad de   instancias con identidades diferentes resultan en desigualdad. UN   la motivación para este comportamiento predeterminado es el deseo de que todos los objetos   debe ser reflexivo (es decir, x es y implica x == y).

y en aras de la coherencia, recomienda:

La comparación de igualdad debe ser reflexiva. En otras palabras, idéntico   los objetos deben comparar igual:

x is y implica x == y

Podemos ver que este es el comportamiento predeterminado para 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 es generalmente verdadero; si algo se prueba como no 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 como no igual a sí mismo:

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

Verificar la identidad puede ser un control mucho más rápido que verificar la igualdad (lo que podría requerir el control recursivo de los miembros).

Pero no puede sustituirse por igualdad, donde puede encontrar más de un objeto como equivalente.

Tenga en cuenta que al comparar la igualdad de listas y tuplas asumiremos 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:

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

Un cuento de advertencia:

La pregunta es intentar usar is para comparar números 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 (de -5 a 256 inclusive) son únicos en Python, en lugar de verificar la igualdad.

Wow, esto puede conducir a algunos errores insidiosos. Tenía un código que marcaba si a es b, que funcionó como yo quería porque a y b suelen ser números pequeños. El error solo ocurrió hoy, después de seis meses en 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 algunos unittest.

Y funcionó en producción, hasta que el código verificó un entero mayor a 256, punto en el cual falló la 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.

Déjame enfatizar: no utilice is para comparar números enteros.


10
2018-01-05 19:33



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

is 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, no forma parte de la especificación del lenguaje


8
2017-09-25 12:31



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

== y is 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 los objetos, por ejemplo, en este caso value1 y value2 referirse a int instancia que almacena el valor 1000:

value1 = 1000
value2 = value1

enter image description here

Porque value2 se refiere al mismo objeto is y == daré True:

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

En el siguiente ejemplo, los nombres value1 y value2 referirse a diferentes int instancias, incluso si ambas almacenan el mismo entero:

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

enter image description here

Porque el mismo valor (entero) se almacena == estarán True, es por eso que a menudo se llama "comparación de valores". sin embargo is regresará False porque estos son diferentes objetos:

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

¿Cuándo usar qué?

En general is es una comparación mucho más rápida. Es por eso que el caché CPython (o quizás reutiliza sería el mejor término) ciertos objetos como enteros pequeños, algunas cadenas, etc. Pero esto debería tratarse como detalle de implementación eso podría (aunque sea poco probable) cambiar en cualquier punto sin previo aviso.

Debieras uso único is si tu:

  • quiero comprobar si dos objetos son realmente el mismo objeto (no solo el mismo "valor"). Un ejemplo puede ser si  usa un objeto singleton como constante.
  • querer comparar un valor a un Pitón constante. Las constantes en Python son:

    • None
    • True1
    • False1
    • NotImplemented
    • Ellipsis
    • __debug__
    • clases (por ejemplo int is int o int is float)
    • podría haber constantes adicionales en módulos incorporados o módulos de terceros. Por ejemplo np.ma.masked del módulo NumPy)

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

¿Puedo personalizar el comportamiento?

Hay algún aspecto de == eso no se ha mencionado ya en las otras respuestas: es parte de Pythons "Modelo de datos". Eso significa que su comportamiento se puede personalizar utilizando el __eq__ método. 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)))

Esto 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 hay otra implementación de __eq__ se puede encontrar en la clase o en las superclases) __eq__ usos is:

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 quieres "más" que solo referencia-comparación para clases personalizadas!

Por otro lado, no puedes personalizar is cheques. Siempre comparará sólo si tienes la misma referencia

¿Estas comparaciones siempre devolverán un booleano?

Porque __eq__ puede volver a implementarse o anularse, no está limitado a devolver True o False. Eso podría devuelve cualquier cosa (¡pero en la mayoría de los casos debería devolver un valor 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 is los cheques siempre regresarán True o False!


1 Como Aaron Hall mencionó en los comentarios:

En general, no debes hacer nada is True o is False comprueba porque uno normalmente utiliza estos "controles" en un contexto que implícitamente convierte el condición a un booleano (por ejemplo, en if declaración). Entonces haciendo el is True comparación y el molde booleano implícito está haciendo más trabajo que simplemente hacer el molde booleano, y te limitas a booleanos (que no se consideran pitónicos).

Como PEP8 menciona:

No compare valores booleanos para True o False utilizando ==.

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

6
2018-01-19 22:21



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

La identidad de un objeto nunca cambia una vez que ha sido creada; puedes pensar que es la dirección del objeto en la memoria.

Puede controlar el comportamiento de comparación de valores de objeto definiendo un __cmp__ método o una comparación rica método como __eq__.


5
2017-09-25 12:34



Echa un vistazo a la pregunta sobre el desbordamiento de la pila El operador "es" de Python se comporta inesperadamente con números enteros.

Lo que básicamente se reduce a eso es que "is"verifica si son el mismo objeto, no solo iguales entre sí (los números debajo de 256 son un caso especial).


3
2017-07-06 06:20