Python中Ellipsis和None的布尔值

5 投票
2 回答
626 浏览
提问于 2025-04-17 09:29

我不太明白为什么EllipsisNone在用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 个回答

1

根据Python的数据模型

如果一个类既没有定义len()方法,也没有定义nonzero()方法,那么这个类的所有实例都会被认为是真值。

None被认为是假的,因为它是一个内置类型,规定了要这样处理。你没有在Ellipsis上定义__len__()__nonzero__(),正如你所说的。如果你希望它被认为是假的,

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

  # or
  def __len__(self):
      return 0
9

bool(x) 的返回值是 True,如果 x 是一个对象,并且没有你提到的那些特殊方法返回 False。这就是为什么 Ellipsis 会被判断为 True 的原因。

Nonebool() 中是一个特殊的情况,它会让这个函数返回 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);
}

撰写回答