python - lenguaje - ¿Hay alguna diferencia entre “foo is None” y “foo== None”?
python tutorial (11)
¿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?
@ 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, "if 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:
La cláusula
is
realmente comprueba si los dosobject
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 mismaid
.Como consecuencia de 1,
is
garantiza si, o no, los dosobject
representados léxicamente tienen atributos idénticos (atributos de atributos ...) o noLa 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 programació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.
Es posible que desee leer esta identidad de objeto y equivalencia .
La declaración ''es'' 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).
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.
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 infact 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.
Para Ninguno no debería haber una diferencia entre la igualdad (==) y la identidad (es). El NoneType probablemente devuelve la identidad para la igualdad. Dado que Ninguno es la única instancia que puede hacer de NingunoTipo (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.
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
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 una prueba de valor booleano, 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))
is
pruebas de identidad, no de igualdad. Para su declaración, 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
es siempre cierto.
In [101]: None is None
Out[101]: True