Python中Ellipsis和None的布尔值
我不太明白为什么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
我是不是漏掉了什么其他的东西,用于判断真假?
还有没有其他对象(除了
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
的原因。
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);
}