Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python bool(Ellipsis) and bool(None)

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
  1. Is there something else I'm missing which is used for truth-testing?

  2. Are there any other objects (besides None) which evaluate to False that implement neither of __len__ or __nonzero__?

like image 212
wim Avatar asked Jan 18 '23 21:01

wim


1 Answers

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);
}
like image 118
yak Avatar answered Jan 29 '23 06:01

yak