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

Brendan Barnwell brenbarn at brenbarn.net
Tue Mar 8 17:16:29 EST 2016


On 2016-03-08 11:54, Chris Angelico wrote:
> On Wed, Mar 9, 2016 at 6:51 AM, Ethan Furman<ethan at stoneleaf.us>  wrote:
>> >So?  Enhance the idea to be allowing
>> >
>> >(expr) as (name) anywhere:
>> >
>> >   if (file.read() as data):
>> >       # process data
>> >
>> >I'm cool with that.  :)
> Well, okay then. Spin that off as its own idea: Name bindings in
> expressions. It's a coherent idea, but it's likely to see some fairly
> stiff opposition :)
>
> (For what it's worth, I am_not_  in opposition to it.)

	I agree that that option should be considered.  I don't see that much 
value in the current proposals because they only handle the case where 
you want to filter the returned values based on those same values, but 
not the case where you want to filter (before or after the map) based on 
some criterion that re-uses a computed expression, or where you want to 
re-use an expression that's not in a comprehension at all.  Something like:

[some_dict[x.lower()] for x in whatever if x.lower() not in 
exclusion_list and x.lower() in some_dict]

	Even though this filter is being done before the map, it's still 
awkward, because you have to keep repeating the .lower().  If we had 
assignment-as-expression, you could do

[some_dict[lx] for x in whatever if lx not in exclusion_list and lx in 
some_dict where lx=x.lower()]

(or whatever the syntax may be).

	Of course, that example is rather silly since the version with the 
"where" is barely shorter :-).  But hopefully the point is clear.  I 
often find myself doing awkward things like the first example in 
numerical situations where I want to collect one thing while filtering 
and mapping based on something else (e.g., work with numbers while 
filtering and mapping based on their logs or something).

	Moreover, a general-purpose assignment-as-expression would also be 
usable in other contexts besides comprehensions.  I run into this same 
repeated-expression thing when doing computations in pandas using 
.apply(), where you do .apply(lambda x: ...), and maybe the ... involves 
a repeated expression involving x.  With assignment-as-expression you 
could .apply(lambda x: ... where temp=f(x)) or what have you

	I think adding assignment-as-expression would be a significant change 
to Python.  I'm not sure whether it would overall be a good change. 
Almost all the cases where I really feel like I want this are cases 
where I'm working with data interactively, and it really is easier to 
use a lambda than define a separate one-off function.  For anything 
larger-scale, I agree that the "problem" can be solved by taking a deep 
breath and writing a separate function or generator comprehension to do 
what you want.  As someone mentioned earlier on this thread, the 
original motivating example:

foo = [abs(x) for x in numbers if abs(x) > 5]

already has a crystal clear solution:

abses = (abs(x) for x in numbers)
foo = [x for x in abses if x > 5]

There is really nothing wrong with this existing solution unless you're 
working interactively and want to do things more tersely.  But if you're 
doing that, you're likely to want to do other kinds of terse expressions 
besides list comprehensions too.

	So basically, to me the issue is much more general than "I want to 
filter after mapping in comprehensions".  What I want is to write 
expressions that re-use an intermediate computation.  Some of those are 
in comprehensions, some aren't.  Most of the cases where I want to do 
this are in interactive situations where I'm using a lot of one-off 
lambdas and temp expressions.  If that's something we want to support 
more, assignment-as-expression could be quite useful, but if we don't, 
it's a different story.

-- 
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."
    --author unknown


More information about the Python-ideas mailing list