I don't understand how are Ellipsis
and None
handled differently by bool()
, when both seem to be identical in terms of the relevant attributes for truth-testing.
>>> bool(Ellipsis)
True
>>> bool(None)
False
>>> any([hasattr(Ellipsis, attr) for attr in ['__len__', '__bool__', '__nonzero__']])
False
>>> any([hasattr(None, attr) for attr in ['__len__', '__bool__', '__nonzero__']])
False
Is there something else I'm missing which is used for truth-testing?
Are there any other objects (besides None
) which evaluate to False
that implement neither of __len__
or __nonzero__
?
bool(x)
is True
if x
is an object without one of the magic methods you mentioned returning False
. That's why Ellipsis
evaluates to True
.
None
is special-cased in bool()
and makes it return False
.
Details:
bool()
uses PyObject_IsTrue()
API function which in 2.7.2 looks like this:
int
PyObject_IsTrue(PyObject *v)
{
Py_ssize_t res;
if (v == Py_True)
return 1;
if (v == Py_False)
return 0;
if (v == Py_None)
return 0;
else if (v->ob_type->tp_as_number != NULL &&
v->ob_type->tp_as_number->nb_nonzero != NULL)
res = (*v->ob_type->tp_as_number->nb_nonzero)(v);
else if (v->ob_type->tp_as_mapping != NULL &&
v->ob_type->tp_as_mapping->mp_length != NULL)
res = (*v->ob_type->tp_as_mapping->mp_length)(v);
else if (v->ob_type->tp_as_sequence != NULL &&
v->ob_type->tp_as_sequence->sq_length != NULL)
res = (*v->ob_type->tp_as_sequence->sq_length)(v);
else
return 1;
/* if it is negative, it should be either -1 or -2 */
return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With