Python bool (Эллипсис) и bool (Нет) - PullRequest
4 голосов
/ 04 января 2012

Я не понимаю, как Ellipsis и None обрабатываются по-разному bool(), когда оба они кажутся идентичными с точки зрения соответствующих атрибутов для проверки правды.

>>> 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. Есть ли что-то еще, что я пропускаю, которое используется для проверки правды?

  2. Есть ли какие-либо другие объекты (кроме None), которые оцениваются в False которые не реализуют ни __len__, ни __nonzero__?

Ответы [ 2 ]

8 голосов
/ 04 января 2012

bool(x) равно True, если x - объект без одного из упомянутых вами магических методов, возвращающих False. Вот почему Ellipsis оценивается как True.

None имеет значение в специальном корпусе в bool() и возвращает его False.

подробности:

bool() использует PyObject_IsTrue() API-функцию, которая в 2.7.2 выглядит следующим образом:

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);
}
1 голос
/ 04 января 2012

Из модели данных Python :

Если класс не определяет ни len (), ни ненулевое (), всеего экземпляры считаются истинными.

None оценивается как ложное, потому что это встроенный тип, который указан для этого .Вы не определили __len__() или __nonzero__() на Ellipsis, как вы заявили.Если вы хотите, чтобы оно оценивалось как false,

class Ellipsis(...):
  #...
  def __nonzero__(self):
      return False

  # or
  def __len__(self):
      return 0
...