[Python-ideas] Provide a 'key' argument for all() and any() builtins

19 views
Skip to first unread message

Giampaolo Rodolà

unread,
Jul 23, 2012, 12:03:24 AM7/23/12
to python...@python.org
This would be similar to 'key' argument already available for min(), max() and sorted() and would let user decide what must be considered True and what not.
Some use cases:


all(a, b, c, ... key=callable)
all(a, b, c, ... key=lambda x: isinstance(x, int))
any(a, b, c, ... key=lambda x: x < 10)

a = b = c = None
for x in foo:
    if cond1:
         a = 0
    elif cond2:
         b = 0
    elif cond3:
         c = 0
# meaning all cond* has been satisfied and it's ok to consider 0 a meaningful value
assert all(a, b, c, key=lambda x: x != None)   


Thoughts?

--- Giampaolo

Raymond Hettinger

unread,
Jul 23, 2012, 12:36:28 AM7/23/12
to Giampaolo Rodolà, python...@python.org

On Jul 22, 2012, at 11:03 PM, Giampaolo Rodolà wrote:

This would be similar to 'key' argument already available for min(), max() and sorted() and would let user decide what must be considered True and what not.

There's no need.   We already have:

    >>> all(predicate(x) for x in iterable)
    >>> any(predicate(x) for x in iterable)


Raymond

Chris Rebert

unread,
Jul 23, 2012, 12:39:13 AM7/23/12
to Giampaolo Rodolà, python...@python.org
On Sun, Jul 22, 2012 at 9:03 PM, Giampaolo Rodolà <g.ro...@gmail.com> wrote:
> This would be similar to 'key' argument already available for min(), max()
> and sorted() and would let user decide what must be considered True and what
> not.
> Some use cases:
>
>
> all(a, b, c, ... key=callable)

You're missing some brackets or parens there:
all([a, b, c, ...], key=callable)

<snip>
> Thoughts?

I see negligible advantage over just writing the generator expression directly:
all(callable(item) for item in iterable)
=== all(iterable, key=callable)
(which is about comparable to the difference between a map()
invocation vs. a list comprehension, and the choice there seems to be
largely a matter of taste)

min() & max() return the result object satisfying the constraint, so
the `key` argument makes sense for when you want to e.g. find the
cheapest house rather than the price of the cheapest house.
In contrast, any() & all() *always* just return a simple bool result,
not the object whose truthiness determined the predicate's result, so
`key` would be pointless since the result gets converted to a plain
bool anyway (or at least, we can conceptualize the implementation as
if it worked that way).

Cheers,
Chris
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Giampaolo Rodolà

unread,
Jul 23, 2012, 7:28:08 AM7/23/12
to Chris Rebert, python...@python.org
2012/7/23 Chris Rebert <pyi...@rebertia.com>
>
> On Sun, Jul 22, 2012 at 9:03 PM, Giampaolo Rodolà <g.ro...@gmail.com> wrote:
> > This would be similar to 'key' argument already available for min(), max()
> > and sorted() and would let user decide what must be considered True and what
> > not.
> > Some use cases:
> >
> >
> > all(a, b, c, ... key=callable)
>
> You're missing some brackets or parens there:
> all([a, b, c, ...], key=callable)
>
> <snip>
> > Thoughts?
>
> I see negligible advantage over just writing the generator expression directly:
> all(callable(item) for item in iterable)

<snip>

> min() & max() return the result object satisfying the constraint, so
> the `key` argument makes sense for when you want to e.g. find the
> cheapest house rather than the price of the cheapest house.
> In contrast, any() & all() *always* just return a simple bool result,
> not the object whose truthiness determined the predicate's result, so
> `key` would be pointless since the result gets converted to a plain
> bool anyway (or at least, we can conceptualize the implementation as
> if it worked that way).


Agreed.
Please ignore my proposal then.

--- Giampaolo
https://code.google.com/p/pyftpdlib/
https://code.google.com/p/psutil/
https://code.google.com/p/pysendfile/

Guido van Rossum

unread,
Jul 23, 2012, 10:55:32 AM7/23/12
to Raymond Hettinger, python...@python.org
In addition, there's a reason why the key= parameter to sort, sorted,
max and min can't be replaced with a similar idiom: all these return
the *original* object(s) and the key= parameter affects only the
comparison; for example, try max(1,-2,3,-4, key=abs).

Whereas for the current proposal, the value returned by the key would
also determine the outcome -- and then there is no advantage over
using the comprehension. More general, if you can first apply the
transformation (the key function) and then the aggregation function
(min/max/etc.), there's no need to combine the transformation and the
aggregation. But in all the cases that have a key= parameter, this is
not so.

--
--Guido van Rossum (python.org/~guido)

Paul Moore

unread,
Jul 23, 2012, 11:18:11 AM7/23/12
to Guido van Rossum, python...@python.org
On 23 July 2012 15:55, Guido van Rossum <gu...@python.org> wrote:
> On Sun, Jul 22, 2012 at 9:36 PM, Raymond Hettinger
> <raymond....@gmail.com> wrote:
>>
>> On Jul 22, 2012, at 11:03 PM, Giampaolo Rodolà wrote:
>>
>> This would be similar to 'key' argument already available for min(), max()
>> and sorted() and would let user decide what must be considered True and what
>> not.
>>
>> There's no need. We already have:
>>
>> >>> all(predicate(x) for x in iterable)
>> >>> any(predicate(x) for x in iterable)
>
> In addition, there's a reason why the key= parameter to sort, sorted,
> max and min can't be replaced with a similar idiom: all these return
> the *original* object(s) and the key= parameter affects only the
> comparison; for example, try max(1,-2,3,-4, key=abs).
>
> Whereas for the current proposal, the value returned by the key would
> also determine the outcome -- and then there is no advantage over
> using the comprehension. More general, if you can first apply the
> transformation (the key function) and then the aggregation function
> (min/max/etc.), there's no need to combine the transformation and the
> aggregation. But in all the cases that have a key= parameter, this is
> not so.

To put it yet another way, the key= parameter encapsulates the
decorate-process-undecorate pattern, and that pattern doesn't apply to
any/all.

Paul.
Reply all
Reply to author
Forward
0 new messages