2008-08-25 11 views
207

¿Hay alguna diferencia entre:¿Hay alguna diferencia entre "foo is None" y "foo == None"?

if foo is None: pass 

y

if foo == None: pass 

La convención que he visto en la mayoría de código Python (y el código yo mismo escribo) es la primera, pero recientemente Vine a través del código que usa el último. Ninguno es una instancia (y la única instancia, IIRC) de NoneType, por lo que no debería importar, ¿no? ¿Hay alguna circunstancia en la que podría?

Respuesta

239

is siempre devuelve True si se compara la misma instancia de objeto

Mientras ==, se determina definitivamente por el método __eq__()

decir


>>> class Foo(object): 
     def __eq__(self, other): 
      return True 

>>> f = Foo() 
>>> f == None 
True 
>>> f is None 
False 
+45

Es posible que desee agregar que None es un singleton por lo que "None is None" es siempre True. –

+39

Y es posible que desee agregar que el operador 'is' no se puede personalizar (sobrecargado por una clase definida por el usuario). – martineau

+0

Entonces, en su caso, ¿por qué el código "f == None" devuelve True? Confundido ... – study

47

Es posible que desee leer este object identity and equivalence.

La declaración 'is' se usa para la identidad del objeto, comprueba si los objetos se refieren a la misma instancia (la misma dirección en la memoria).

Y la instrucción '==' se refiere a igualdad (mismo valor).

+0

Hmmm, creo que su enlace ha cambiado, a menos que esté interesado en * cómo llamar a las funciones externas desde python * – Pat

4

Para None no debería haber una diferencia entre igualdad (==) e identidad (es). El NoneType probablemente devuelva la identidad para la igualdad. Como None es la única instancia que puede hacer de NoneType (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 "Igualdad", ya que las listas tienen una operación de comparación que no es el valor por defecto de regresar de la identidad.

4

@Jason:

le recomiendo usar algo más en la línea de

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

no me gusta usar "si foo:" a menos que foo realmente representa un valor booleano (es decir, 0 o 1). Si foo es una cadena o un objeto u otra cosa, "if foo:" puede funcionar, pero parece un atajo perezoso para mí. Si está comprobando si x es None, diga "si x es None:".

+0

Verificar las cadenas vacías/listas con "si var" es la forma preferida. La conversión booleana está bien definida, y es menos código que incluso se comporta mejor. No hay razón para hacer "if len (mylist) == 0" por ejemplo. – truppo

+0

incorrecto Supongamos que foo = "". Luego 'if foo' devolverá false y el comentario' #foo is None' es incorrecto. – blokeley

+0

Nota para los detractores: mi respuesta es citar una respuesta que desde entonces se ha eliminado y no está de acuerdo con ella. Si 'no' me gusta el código en mi respuesta, debe'upvote_ '. :-) –

23

Una palabra de precaución:

if foo: 
    # do something 

Es no exactamente lo mismo que:

if x is not None: 
    # do something 

La primera es una prueba de valor booleano y se pueden evaluar en false en diferentes contextos. Hay varias cosas que representan false en un valor booleano pruebas, por ejemplo, contenedores vacíos, valores booleanos. Ninguno también evalúa como falso en esta situación, pero también lo hacen otras cosas.

12

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

+6

... pero (ob es ob2) es MUCHO más rápido. Timeit dice que "(a es b)" es 0.0365 usec por ciclo y "(id (a) == id (b))" es 0.153 usec por ciclo. ¡4.2 veces más rápido! – AKX

+4

la versión 'is' no necesita ninguna llamada de función, ni ninguna búsqueda de atributo de intérprete de Python; el intérprete puede responder inmediatamente si ob1 es, de hecho, ob2. – u0b34a0f6ae

+15

No, no es así. '{} es {}' es falso y 'id ({}) == id ({})' puede ser (y ** es ** en CPython) verdadero. Ver http://stackoverflow.com/questions/3877230 –

11

La razón foo is None es la forma preferida es que puede ser el manejo de un objeto que define su propio __eq__, y que define el objeto a ser igual a ninguno. Por lo tanto, siempre use foo is None si necesita ver si es de hecho None.

1

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 
>>> 

Desde None es un producto único, x == None y x is None tendría el mismo resultado. Sin embargo, en mi opinión estética, x == None es lo mejor.

+2

No estoy de acuerdo con la opinión al final de esta respuesta. Cuando se compara con ninguno explícitamente, generalmente se pretende que el objeto en cuestión sea exactamente el objeto 'Ninguno'. En comparación, rara vez se ve a Ninguno usado en ningún otro contexto excepto para ser similar a 'False' con otros valores como verdaderos. En esos casos es más idiomático hacer algo como 'if x: pass' – SingleNegationElimination

1

Algunos detalles más:

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

  2. Como consecuencia de 1, is asegura de si, o no, los dos léxico representado object s tienen atributos idénticos (atributos-de-atributos ...) o no

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

E.g.

>>> 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 puesto NoneType sólo puede tener una instancia de sí mismo en la tabla "look-up" de la pitón, por tanto, los primeros y los segundos son más de un estilo de programación del desarrollador que escribió el código (tal vez para mantener la coherencia) en lugar de tener una razón lógica sutil para elegir uno sobre el otro.

+2

Todos leyendo esto: NO use' some_string is "bar" 'para comparar cadenas NUNCA. NO HAY UNA ÚNICA RAZÓN ACEPTABLE para hacerlo y SE ROMPARÁ cuando no lo espere. El hecho de que funcione a menudo es simplemente porque CPython sabe que sería estúpido crear dos objetos inmutables que tengan el mismo contenido. Pero puede suceder sin embargo. – ThiefMaster

+0

@ThiefMaster ¿tiene la respuesta la tendencia a ser malinterpretada? Sin embargo, al leerlo nuevamente * I * no pude encontrarlo (con la mención de "algunas excepciones"). Su declaración solo se cumple para cadenas y no 'int', ¿verdad? –

+0

No realmente, pero como tiene ese ejemplo en su respuesta, pensé que sería una buena idea advertir a los usuarios que no es una buena idea usarlo. Tal vez agregue algo como "# cpython specific/not guaranteed" detrás de esa línea ... – ThiefMaster

8

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

comparaciones con embarazos únicos como Ninguno siempre se debe hacer con es o no es, nunca los operadores de igualdad.

4

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

== por otro lado, pruebas de igualdad según lo determinado por el método __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. Entonces None is None es siempre cierto.

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