¿Hay alguna diferencia entre “foo is None” y “foo == None”?

¿Hay alguna diferencia entre:

if foo is None: pass 

y

 if foo == None: pass 

La convención que he visto en la mayoría de los códigos Python (y el código que escribo yo mismo) es el primero, pero recientemente encontré un código que usa el último. Ninguna es una instancia (y la única, IIRC) de NoneType, por lo que no debería importar, ¿verdad? ¿Hay alguna circunstancia en la que pueda hacerlo?

Siempre devuelve True si compara la misma instancia de objeto.

Mientras que == está determinado en última instancia por el __eq__()

es decir

 >>> class Foo(object): def __eq__(self, other): return True >>> f = Foo() >>> f == None True >>> f is None False 

Es posible que desee leer esta identidad de objeto y equivalencia .

La statement ‘is’ se usa para la identidad del objeto, verifica si los objetos se refieren a la misma instancia (la misma dirección en la memoria).

Y la statement ‘==’ se refiere a la igualdad (mismo valor).

Una palabra de precaución:

 if foo: # do something 

No es exactamente lo mismo que:

 if x is not None: # do something 

El primero es una prueba de valor booleano y se puede evaluar como falso en diferentes contextos. Hay una serie de cosas que representan falso en las pruebas de valores booleanos, por ejemplo, contenedores vacíos, valores booleanos. Ninguno también se evalúa como falso en esta situación, pero otras cosas también lo hacen.

(ob1 is ob2) igual a (id(ob1) == id(ob2))

La razón por la que foo is None es que la forma preferida es que podría estar manejando un objeto que define su propio __eq__ , y que define que el objeto es igual a None. Por lo tanto, siempre use foo is None si necesita ver si es de hecho None .

No hay diferencia porque los objetos que son idénticos, por supuesto, serán iguales. Sin embargo, PEP 8 indica claramente que debe usar is :

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

is pruebas de identidad, no de igualdad. Para su statement, foo is none , Python simplemente compara la dirección de memoria de los objetos. Significa que está haciendo la pregunta “¿Tengo dos nombres para el mismo objeto?”

== por otra parte, prueba la igualdad según lo determinado por el __eq__() . No le importa la identidad.

 In [102]: x, y, z = 2, 2, 2.0 In [103]: id(x), id(y), id(z) Out[103]: (38641984, 38641984, 48420880) In [104]: x is y Out[104]: True In [105]: x == y Out[105]: True In [106]: x is z Out[106]: False In [107]: x == z Out[107]: True 

None es un operador de singleton. Así que None is None siempre es cierto.

 In [101]: None is None Out[101]: True 

Para Ninguno, no debería haber una diferencia entre igualdad (==) e identidad (es). El NoneType probablemente devuelve la identidad para la igualdad. Dado que Ninguno es la única instancia que puede hacer del tipo Ninguno (creo que esto es cierto), las dos operaciones son las mismas. En el caso de otros tipos, este no es siempre el caso. Por ejemplo:

 list1 = [1, 2, 3] list2 = [1, 2, 3] if list1==list2: print "Equal" if list1 is list2: print "Same" 

Esto imprimiría “Igual”, ya que las listas tienen una operación de comparación que no es la devolución de identidad predeterminada.

@ Jason :

Recomiendo usar algo más en la línea de

 if foo: #foo isn't None else: #foo is None 

No me gusta usar “if foo:” a menos que foo realmente represente un valor booleano (es decir, 0 o 1). Si foo es una cadena o un objeto u otra cosa, “si foo:” puede funcionar, pero me parece un atajo perezoso. Si está comprobando si x es Ninguno, diga “si x es Ninguno:”.

Algunos detalles más:

  1. La cláusula is realmente comprueba si los dos object están en la misma ubicación de memoria o no. es decir, si ambos apuntan a la misma ubicación de memoria y tienen la misma id .

  2. Como consecuencia de 1, is asegura si, o no, los dos object representados léxicamente tienen atributos idénticos (atributos de atributos …) o no

  3. La creación de instancias de tipos primitivos como bool , int , string (con alguna excepción), NoneType con el mismo valor siempre estará en la misma ubicación de memoria.

P.ej

 >>> int(1) is int(1) True >>> str("abcd") is str("abcd") True >>> bool(1) is bool(2) True >>> bool(0) is bool(0) True >>> bool(0) False >>> bool(1) True 

Y dado que NoneType solo puede tener una instancia de sí mismo en la tabla de “consulta” de python, por lo tanto, el primero y el último son más un estilo de progtwigción del desarrollador que escribió el código (quizás por coherencia) en lugar de tener una razón lógica sutil para elegir uno sobre el otro.

La conclusión de John Machin de que None es un singleton es una conclusión reforzada por este código.

 >>> x = None >>> y = None >>> x == y True >>> x is y True >>> 

Dado que None es un singleton, x == None y x is None tendrían el mismo resultado. Sin embargo, en mi opinión estética, x == None es la mejor.

 a is b # returns true if they a and b are true alias a == b # returns true if they are true alias or they have values that are deemed equivalence a = [1,3,4] b = a[:] #creating copy of list a is b # if gives false False a == b # gives true True