¿Existe alguna diferencia entre "foo es Ninguno" y "foo == Ninguno"?
-
09-06-2019 - |
Pregunta
¿Hay alguna diferencia entre:
if foo is None: pass
y
if foo == None: pass
La convención que he visto en la mayoría del código Python (y en el código que yo mismo escribo) es la primera, pero recientemente encontré un código que usa la segunda.Ninguno es una instancia (y la única instancia, IIRC) de NoneType, por lo que no debería importar, ¿verdad?¿Hay alguna circunstancia en la que podría ser así?
Solución
is
siempre regresa True
si compara la misma instancia de objeto
Mientras ==
está determinada en última instancia por la __eq__()
método
es decir.
>>> class Foo(object):
def __eq__(self, other):
return True
>>> f = Foo()
>>> f == None
True
>>> f is None
False
Otros consejos
Quizás quieras leer esto. identidad y equivalencia del objeto.
La declaración '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 declaración '==' se refiere a la igualdad (mismo valor).
Una palabra de precaución:
if foo:
# do something
Es no exactamente el mismo que:
if x is not None:
# do something
La primera es una prueba de valor booleano y puede evaluarse como falso en diferentes contextos.Hay una serie de cosas que representan falso en 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 foo is None
La forma preferida es que podría estar manejando un objeto que define su propio __eq__
, y eso define el objeto como igual a Ninguno.Por lo tanto, utilice siempre foo is None
si necesitas ver si es de hecho None
.
No hay diferencia porque los objetos que son idénticos, por supuesto, serán iguales.Sin embargo, PEPE 8 indica claramente que debes usar is
:
Las comparaciones con singletons como None siempre deben realizarse con is o not is, nunca con los operadores de igualdad.
is
pruebas de identidad, no igualdad.Para tu 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 determinadas por el __eq__()
método.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 singleton.Entonces 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 identidad por igualdad.Dado que None es la única instancia que puede crear de NoneType (creo que esto es cierto), las dos operaciones son iguales.En el caso de otros tipos esto no siempre es así.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 parecido a
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, un objeto o algo más, "if foo:" puede funcionar, pero a mí me parece un atajo vago.Si está comprobando si x es Ninguno, diga "si x es Ninguno:".
Algunos detalles más:
El
is
La cláusula realmente verifica si los dosobject
S 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 lo mismoid
.Como consecuencia de 1,
is
garantiza si, o no, los dos representados léxicamenteobject
s tienen atributos idénticos (atributos-de-atributos...) o noCreación de instancias de tipos primitivos como
bool
,int
,string
(con alguna excepción),NoneType
tener 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 desde NoneType
sólo puede tener una instancia de sí mismo en la tabla de "búsqueda" de Python, por lo tanto, el primero y el segundo son más un estilo de programación del desarrollador que escribió el código (tal vez 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 respaldada por este código.
>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>>
Desde None
es un singleton, x == None
y x is None
tendría el mismo resultado.Sin embargo, en mi opinión estética, x == None
es 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