En la primera prueba, Python intenta convertir el objeto a un valor bool
si aún no lo es. Aproximadamente, le preguntamos al objeto: ¿tiene sentido o no? Esto se realiza utilizando el siguiente algoritmo:
Si el objeto tiene un método especial __nonzero__
(como lo hacen numéricos muebles empotrados, int
y float
), se llama a este método. Debe devolver un valor bool
que luego se usa directamente, o un valor int
que se considera False
si es igual a cero.
De lo contrario, si el objeto tiene un método especial __len__
(como hacen contenedores empotrados, list
, dict
, set
, tuple
, ...), se llama a este método, teniendo en cuenta un recipiente False
si está vacío (la longitud es cero).
De lo contrario, el objeto se considera True
a menos que sea None
en cuyo caso, se considera False
.
En la segunda prueba, el objeto se compara por igualdad con None
. Aquí, le preguntamos al objeto: "¿Es usted igual a este otro valor?" Esto se realiza utilizando el siguiente algoritmo:
Si el objeto tiene un método __eq__
, se llama, y el valor de retorno se convierte después en un valor bool
y se utiliza para determinar el resultado de la if
.
De lo contrario, si el objeto tiene un método __cmp__
, se llama. Esta función debe devolver un int
que indica el orden de los dos objetos (-1
si self < other
, 0
si self == other
, +1
si self > other
).
De lo contrario, los objetos se comparan para la identidad (es decir, son referencia del mismo objeto, como puede ser probado por el operador is
).
Hay otra prueba posible con el operador is
. Le estaríamos preguntando al objeto, "¿Es usted este objeto en particular?"
En general, recomendaría usar la primera prueba con valores no numéricos, para usar la prueba de igualdad cuando quiera comparar objetos de la misma naturaleza (dos cadenas, dos números, ...) y para verificar la identidad solo cuando se usan valores centinela (None
significando que no se inicializó para un campo de miembro, por ejemplo, o cuando se usan los métodos getattr
o __getitem__
).
En resumen, tenemos:
>>> class A(object):
... def __repr__(self):
... return 'A()'
... def __nonzero__(self):
... return False
>>> class B(object):
... def __repr__(self):
... return 'B()'
... def __len__(self):
... return 0
>>> class C(object):
... def __repr__(self):
... return 'C()'
... def __cmp__(self, other):
... return 0
>>> class D(object):
... def __repr__(self):
... return 'D()'
... def __eq__(self, other):
... return True
>>> for obj in ['',(), [], {}, 0, 0., A(), B(), C(), D(), None]:
... print '%4s: bool(obj) -> %5s, obj == None -> %5s, obj is None -> %5s' % \
... (repr(obj), bool(obj), obj == None, obj is None)
'': bool(obj) -> False, obj == None -> False, obj is None -> False
(): bool(obj) -> False, obj == None -> False, obj is None -> False
[]: bool(obj) -> False, obj == None -> False, obj is None -> False
{}: bool(obj) -> False, obj == None -> False, obj is None -> False
0: bool(obj) -> False, obj == None -> False, obj is None -> False
0.0: bool(obj) -> False, obj == None -> False, obj is None -> False
A(): bool(obj) -> False, obj == None -> False, obj is None -> False
B(): bool(obj) -> False, obj == None -> False, obj is None -> False
C(): bool(obj) -> True, obj == None -> True, obj is None -> False
D(): bool(obj) -> True, obj == None -> True, obj is None -> False
None: bool(obj) -> False, obj == None -> True, obj is None -> True
general 'someObj es None' es preferible 'someObj == None' –
¿qué pasa con pseudocódigo si X no es ninguno? O 'X! = Ninguno'? –
esta pregunta es más detallado que los otros ... felicitaciones ... – alamin