[Python-ideas] Map-then-filter in comprehensions

Chris Angelico rosuav at gmail.com
Tue Mar 8 15:16:21 EST 2016


On Wed, Mar 9, 2016 at 7:06 AM, Pavol Lisy <pavol.lisy at gmail.com> wrote:
> 2016-03-08 15:17 GMT+01:00, Allan Clark <allan.clark at gmail.com>:
> [...]
>>     [y for x in numbers if abs(x) as y > 5]
> [...]
>>     * It would need to be decided whether you allowed multiple 'as'
>> expression in the condition, particularly using 'and' or 'or' as in 'if
>> f(a) as x > 5 and f(b) as y > 5'
>
> Just small idea not to forget here:
>
> [y+z for x in numbers if abs(x) as y > 5 or x**2 as z>100]
>
> "or" is short-circuit operator so z could be not (well) defined.

Enforcing that the order of operations is as you're implying:

[y+z for x in numbers if (abs(x) as y) > 5 or (x**2 as z) > 100]

If the first condition is true, the second will not be evaluated.
It'll be equivalent to:

def <listcomp>():
    result = []
    for x in numbers:
        y = abs(x)
        if y > 5:
            result.append(y+z)
        else:
            z = x**2
            if z > 100: result.append(y+z)
    return result

So, yeah, that could surprise a *lot* of people. Either an
UnboundLocalError, or retaining the value from the previous iteration.

Recommendation: If you use name bindings in the second half, use
bitwise operators instead:

[y+z for x in numbers if (abs(x) as y) > 5 | (x**2 as z) > 100]

That'll force both sides to be evaluated. (Downside: It's reliable
only if you actually have True and False.)

ChrisA


More information about the Python-ideas mailing list