Do not promote `None` as the first argument to `filter` in documentation.
Peter Otten
__peter__ at web.de
Tue Mar 6 10:41:38 EST 2018
Chris Angelico wrote:
> On Wed, Mar 7, 2018 at 2:12 AM, Kirill Balunov <kirillbalunov at gmail.com>
> wrote:
>>
>>
>> 2018-03-06 17:55 GMT+03:00 Chris Angelico <rosuav at gmail.com>:
>>>
>>> On Wed, Mar 7, 2018 at 1:48 AM, Kirill Balunov <kirillbalunov at gmail.com>
>>> wrote:
>>> > Note: For some historical reasons as the first argument you can use
>>> > None instead of function, in this case the identity function is
>>> > assumed. That is, all elements of iterable that are false are removed
>>> > which is equivalent
>>> > to (item for item in iterable if item). Currently, for the same
>>> > purpose the
>>> > preferred form is `filter(bool, iterable)`.
>>> >
>>>
>>> I'd prefer to word it something like:
>>>
>>> If the first argument is None, the identity function is assumed. That
>>> is, all elements of the iterable that are false are removed; it is
>>> equivalent to (item for item in iterable if item). It is approximately
>>> equivalent to (but faster than) filter(bool, iterable).
>>>
>>> ChrisA
>>> --
>>> https://mail.python.org/mailman/listinfo/python-list
>>
>>
>> I do not want to seem rude and stubborn, but how much faster is it to
>> highlight or emphasize it:
>>
>
> Timings mean little. Why do we write:
>
> if lst:
>
> instead of:
>
> if bool(lst):
>
> ? Because it's unnecessary and pointless to call bool() on something
> before using it in a boolean context. If that concept causes you
> problems, it's not the fault of the filter function; filter simply
> uses something in a boolean context.
>
> So "the identity function" is more correct than "the bool() function".
Fun fact: CPython handles filter(bool) and filter(None) the same way, it
sets the checktrue flag and chooses the fast path:
static PyObject *
filter_next(filterobject *lz)
{
PyObject *item;
PyObject *it = lz->it;
long ok;
PyObject *(*iternext)(PyObject *);
int checktrue = lz->func == Py_None || lz->func == (PyObject
*)&PyBool_Type;
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
item = iternext(it);
if (item == NULL)
return NULL;
if (checktrue) {
ok = PyObject_IsTrue(item);
} else {
PyObject *good;
good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);
if (good == NULL) {
Py_DECREF(item);
return NULL;
}
ok = PyObject_IsTrue(good);
Py_DECREF(good);
}
if (ok > 0)
return item;
Py_DECREF(item);
if (ok < 0)
return NULL;
}
}
If there were a built-in identity() function it could be treated the same
way.
More information about the Python-list
mailing list