Two small functional-style-related improvements

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). 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 What do you think? *j

On 27/03/2011 03:30, 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).
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
What do you think? *j
I think that suggestion 2 is a strange one! :-)

Jan Kaliszewski <zuo@chopin.edu.pl> writes:
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))
Why so specific? What's wrong with ‘operator.is_(x, None)’ and ‘operator.is_not(x, None)’? Those both work today.
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 one seems overkill for the standard library. -- \ “When cryptography is outlawed, bayl bhgynjf jvyy unir | `\ cevinpl.” —Anonymous | _o__) | Ben Finney

Ben Finney dixit (2011-03-27, 14:14):
Jan Kaliszewski <zuo@chopin.edu.pl> writes:
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))
Why so specific?
None is quite specific (and widely used in different contexts) and is None/is not None tests are very common.
What's wrong with ‘operator.is_(x, None)’ and ‘operator.is_not(x, None)’? Those both work today.
But cannot be used quickly with all(), any(), filter(), takewhile(), dropwhile() etc. without ugly lambda or playing with partial(). Which one of the following do you prefer? * filter((lambda x: x is None), iterable) * filter(functools.partial(operator.is_, None), iterable) * filter(None, (x is None for x in iterable)) * filter(operator.is_none, iterable)
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 one seems overkill for the standard library.
But itertools.filterfalse() was added -- which is counterpart for filter(). Why not to cover also all(), any(), takewhile(), dropwhile() etc. with only one additional function? Regards. *j

On Sun, Mar 27, 2011 at 01:53:26PM +0200, Jan Kaliszewski wrote:
Which one of the following do you prefer?
* filter((lambda x: x is None), iterable) * filter(functools.partial(operator.is_, None), iterable) * filter(None, (x is None for x in iterable)) * filter(operator.is_none, iterable)
I prefer [x for x in iterable if x is not None] Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Jan Kaliszewski <zuo@chopin.edu.pl> writes:
Which one of the following do you prefer?
* filter((lambda x: x is None), iterable) * filter(functools.partial(operator.is_, None), iterable) * filter(None, (x is None for x in iterable)) * filter(operator.is_none, iterable)
(x for x in iterable if x is None) -- \ “The Way to see by Faith is to shut the Eye of Reason.” | `\ —Benjamin Franklin | _o__) | Ben Finney

Ben Finney dixit (2011-03-27, 23:46):
Jan Kaliszewski <zuo@chopin.edu.pl> writes:
Which one of the following do you prefer?
* filter((lambda x: x is None), iterable) * filter(functools.partial(operator.is_, None), iterable) * filter(None, (x is None for x in iterable)) * filter(operator.is_none, iterable)
(x for x in iterable if x is None)
Yeah, you're right. To less sleep... But anyway, I'd prefer filter(is_none, iterable) :) *j

Jan Kaliszewski <zuo@chopin.edu.pl> writes:
But anyway, I'd prefer filter(is_none, iterable) :)
Feel free to write such a function for your code, then. I don't see how it's important enough to be in the Python standard library. -- \ “Ridicule is the only weapon which can be used against | `\ unintelligible propositions.” —Thomas Jefferson, 1816-07-30 | _o__) | Ben Finney

Ben Finney dixit (2011-03-28, 00:16):
Jan Kaliszewski <zuo@chopin.edu.pl> writes:
But anyway, I'd prefer filter(is_none, iterable) :)
Feel free to write such a function for your code, then. I don't see how it's important enough to be in the Python standard library.
But what about dropwhile, takewhile and other predicate-based functions that do not have simple gen-exp/comprehension counterparts? Redards. *j

On 3/27/2011 7:53 AM, Jan Kaliszewski wrote:
Which one of the following do you prefer?
* filter((lambda x: x is None), iterable) * filter(functools.partial(operator.is_, None), iterable)
These two produce an iterable of Nones, one for each None in the original iterable. I have trouble imagining a real use case for this. I can see a use cases for dropping everything but None. This can, of course, always be done at the point of use: for ob in iterable: if ob is not None: do_something(ob) If you want to separate the conditional from the action and hide the conditional, then write a trivial, specific, filter generator: def dropNone(it): for ob in it: if ob is not None: yield ob for ob in dropNone(iterable): do_something(ob) For repeated use, I prefer dropNone to any filter version, including your proposal.
* filter(None, (x is None for x in iterable))
This is not the same thing as the above as it instead produces an iterable of Trues, one for each None in iterable. -- Terry Jan Reedy

On 2011-03-27, at 05:14 , Ben Finney wrote:
Jan Kaliszewski <zuo@chopin.edu.pl> writes:
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))
Why so specific? What's wrong with ‘operator.is_(x, None)’ and ‘operator.is_not(x, None)’? Those both work today. It would be nice if the binary pseudo-operators in ``operator`` supported right sections though: what would be really nifty here would be to write
predicate_user(operator.is_(None), collection) and have it behave as predicate_user(lambda value: operator.is_(value, None), collection) (note: order is important, I think the most common use case for non-commutative operator sections is to fix the second operand). This would not only obviate the purported need for an ``is_none`` operator method, it would make operator far more interesting for all higher-order tasks.

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@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@sylar ~]$ python3 -m timeit -r 15 "42 is None" 1000000 loops, best of 15: 0.117 usec per loop For comparison purposes: [steve@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@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

Steven D'Aprano dixit (2011-03-27, 14:41):
Jan Kaliszewski wrote: [...]
* 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)
It isn't indeed -- but I'd prefer e.g.: filter(is_not_none, iterable) ...rather than: filter(None, (x is not None for x in iterable)) (not saying about more complex cases, when additional inner for-loop makes the expression much less readable). And --what is maybe more important-- such functions as itertools.dropwhile, itertools.takewhile, itertools.groupby (together with .sort/sorted) do not have their generator expression counterparts (at least resonably simple ones). Ane then, if we wish to stay in the functional-style we must use ugly lambdas/partial for now.
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.
Yes, maybe rather: functools.negated
Either way, I don't see the point to it. [...] What is your use-case for this function?
I'd would like to be able to do: assert any(dropwhile(negated(str.isalnum), takewhile(negated(str.isspace), my_names))) ...instead of: assert any(dropwhile(lambda name: not name.isalnum(), takewhile(lambda name: not name.isspace(), my_names))) Regards. *j

On 27 March 2011 14:05, Jan Kaliszewski <zuo@chopin.edu.pl> wrote:
I'd would like to be able to do:
assert any(dropwhile(negated(str.isalnum), takewhile(negated(str.isspace), my_names)))
...instead of:
assert any(dropwhile(lambda name: not name.isalnum(), takewhile(lambda name: not name.isspace(), my_names)))
Do you honestly find *either* of those readable? I can't even work out what they do well enough to try to come up with an alternative version using generator expressions... If I needed an assertion like that, I'd write a function with a name that explains what's going on, which does the whole of that dropwhile-takewhile routine (probably using multiple lines, with comments) and then use that as assert(any(whatever_this_is(my_names))). -1 on putting anything in the stdlib which encourages obfuscated code like that. (Note: If that style suits you, then writing your own functions in your codebase to support it is fine, I just don't see it as something the stdlib should be doing). Paul.

On 3/27/2011 10:38 AM, Paul Moore wrote:
On 27 March 2011 14:05, Jan Kaliszewski<zuo@chopin.edu.pl> wrote:
I'd would like to be able to do:
assert any(dropwhile(negated(str.isalnum), takewhile(negated(str.isspace), my_names)))
...instead of:
assert any(dropwhile(lambda name: not name.isalnum(), takewhile(lambda name: not name.isspace(), my_names)))
Do you honestly find *either* of those readable? I can't even work out what they do well enough to try to come up with an alternative version using generator expressions...
Me neither, not without more motivation than list reading.
If I needed an assertion like that, I'd write a function with a name that explains what's going on, which does the whole of that dropwhile-takewhile routine (probably using multiple lines, with comments) and then use that as assert(any(whatever_this_is(my_names))).
Ditto. And once the function is abstracted and named, the detailed implementation does not matter so much.
-1 on putting anything in the stdlib which encourages obfuscated code like that. (Note: If that style suits you, then writing your own functions in your codebase to support it is fine, I just don't see it as something the stdlib should be doing).
-- Terry Jan Reedy
participants (8)
-
Ben Finney
-
Jan Kaliszewski
-
Masklinn
-
MRAB
-
Oleg Broytman
-
Paul Moore
-
Steven D'Aprano
-
Terry Reedy