Pet*_*sen 41 python set truthiness
我有兴趣在Python的真值设置像{'a', 'b'},或空集set()(这是不一样的空字典{}).我特别想知道是否bool(my_set)是False当且仅当设定my_set为空.
忽略原语(如数字)以及用户定义的类型,https://docs.python.org/3/library/stdtypes.html#truth表示:
以下值被视为false:
- [...]
- 任何空序列,例如
'',(),[].- 例如,任何空映射
{}.- [...]
所有其他值都被认为是真实的
据https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range,一组是不是一个序列(它是无序的,它的元素没有索引,等等. ):
有三种基本序列类型:列表,元组和范围对象.
而且,根据https://docs.python.org/3/library/stdtypes.html#mapping-types-dict,
目前只有一种标准的映射类型,即字典.
所以,据我所知,set类型不是一种类型False.但是,当我尝试时,bool(set())评估为False.
问题:
False吗?Ale*_*agh 30
在查看CPython的源代码之后,我猜这是一个文档错误,但是,它可能是依赖于实现的,因此在Python bug跟踪器上引发一个很好的问题.
具体来说,object.c定义项的真值如下:
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_bool != NULL)
res = (*v->ob_type->tp_as_number->nb_bool)(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);
}
Run Code Online (Sandbox Code Playgroud)
我们可以清楚地看到,如果值不是布尔类型,None,序列或映射类型,则值将始终为true,这将需要设置tp_as_sequence或tp_as_mapping.
幸运的是,查看setobject.c表明集合确实实现了tp_as_sequence,这表明文档似乎不正确.
PyTypeObject PySet_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"set", /* tp_name */
sizeof(PySetObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)set_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)set_repr, /* tp_repr */
&set_as_number, /* tp_as_number */
&set_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
/* ellipsed lines */
};
Run Code Online (Sandbox Code Playgroud)
Dicts也实现了tp_as_sequence,所以看起来虽然它不是序列类型,但它类似于序列,足以让它变得真实.
在我的观点中,文档应该澄清这一点:类似映射的类型或类似序列的类型将依赖于它们的长度.
编辑作为user2357112正确地指出,tp_as_sequence而tp_as_mapping并不意味着类型是序列或映射.例如,dict实现tp_as_sequence和列表实现tp_as_mapping.
a_g*_*est 26
有关__bool__状态的文档说明此方法被调用以进行真值测试,如果未定义,则__len__评估:
被称为实施真值测试和内置操作bool(); [...]如果未定义此方法,
__len__()则调用(如果已定义),并且如果对象的结果非零,则认为该对象为true.如果一个类既未定义也__len__()未定义__bool__(),则其所有实例都被视为真.
这适用于任何Python对象.我们可以看到set没有定义方法__bool__:
>>> set.__bool__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'set' has no attribute '__bool__'
Run Code Online (Sandbox Code Playgroud)
所以真相测试依赖于__len__:
>>> set.__len__
<slot wrapper '__len__' of 'set' objects>
Run Code Online (Sandbox Code Playgroud)
因此,只有空集(零长度)被视为假.
关于这方面,文档中真值测试的部分并不完整.
use*_*ica 18
这部分文档写得不好,或者说维护得很差.以下条款:
用户定义的类的实例,如果类定义了一个
__bool__()或__len__()方法,则该方法返回整数零或bool值False.
真正适用于所有类,用户定义与否,包括set,dict甚至所有其他子句中列出的类型(所有这些都定义了__bool__或者__len__).(在Python 2中,None尽管没有__len__Python 2的等价物__bool__,但它是假的,但是自Python 3.3以来该例外已经消失了.)
我说维护得很差,因为这部分至少从Python 1.4开始几乎没有变化,也许更早.它已更新为添加False和删除单独的int/long类型,但不适用于类型/类统一或集合的引入.
回到引用的quoted子句时,用户定义的类和内置类型确实表现得不同,我认为内置类型实际上没有__bool__或__len__当时.
| 归档时间: |
|
| 查看次数: |
3282 次 |
| 最近记录: |