[Python-ideas] Two small functional-style-related improvements
Steven D'Aprano
steve at pearwood.info
Sun Mar 27 05:41:44 CEST 2011
Jan Kaliszewski wrote:
> Hello.
>
> IMHO it'd be nice...
>
> 1. ...to add:
>
> * operator.is_none -- equivalent to (lambda x: x is None))
> * operator.is_not_none -- equivalent tolambda x: x is not None))
>
> ...making using 'is None'/'is not None' tests with any(), all(),
> filter(), itertools.takewhile/dropwhile() more convenient and readable
> (possibly also optimised for speed).
How is
import operator
any(map(operator.is_none, iterable))
more convenient and readable than:
any(x is None for x in iterable)
? I'm asking this as someone who likes map and other functional tools.
Now that we have generator expressions and list comprehensions in the
language, wrapping trivial expressions in a function is far less common.
Likewise, how could a function call that includes 'x is None' be faster
than 'x is None' alone? The overhead of calling the function would have
to be negative! We can see this with the existing operator.is_ function:
[steve at sylar ~]$ python3 -m timeit -r 15 -s "from operator import is_"
"is_(42, None)"
1000000 loops, best of 15: 0.224 usec per loop
[steve at sylar ~]$ python3 -m timeit -r 15 "42 is None"
1000000 loops, best of 15: 0.117 usec per loop
For comparison purposes:
[steve at sylar ~]$ python3 -m timeit -r 15 -s "def f(x): x is None" "f(42)"
1000000 loops, best of 15: 0.378 usec per loop
and just for completeness:
[steve at sylar ~]$ python3 -m timeit -r 15 -s "from operator import is_;
from functools import partial; f = partial(is_, None)" "f(42)"
1000000 loops, best of 15: 0.301 usec per loop
The possible time saving compared to a pure-Python function is very
small, and there's rarely a need to use a function when you can just use
an expression.
> 2. ...to add:
>
> * operator.anti_caller (or e.g. functools.negator?) -- equivalent to:
>
> def anti_caller(func):
> def call_and_negate(*args, **kwargs):
> return not func(*args, **kwargs)
> return call_and_negate
This seems to be a decorator, so I don't believe it belongs in the
operator module. Either way, I don't see the point to it. Why would you
use this
@functools.negator
def spam(x):
return something
instead of just this?
def spam(x):
return not something
What is your use-case for this function?
--
Steven
More information about the Python-ideas
mailing list