After looking at the source code for CPython, I would guess this is a documentation error, however, it could be implementation dependent and therefore would be a good issue to raise on the Python bug tracker.
Specifically, object.c defines the truth value of an item as follows:
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);
}
We can clearly see that the value is value would be always true if it is not a boolean type, None, a sequence, or a mapping type, which would require tp_as_sequence or tp_as_mapping to be set.
Fortunately, looking at setobject.c shows that sets do implement tp_as_sequence, suggesting the documentation seems to be incorrect.
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 */
};
Dicts also implement tp_as_sequence, so it seems that although it is not a sequence type, it sequence-like, enough to be truthy.
In my opionion, the documentation should clarify this: mapping-like types, or sequence-like types will be truthy dependent on their length.
Edit As user2357112 correctly points out, tp_as_sequence and tp_as_mapping do not mean the type is a sequence or a map. For example, dict implements tp_as_sequence, and list implements tp_as_mapping.