[Python-ideas] More power in list comprehensions with the 'as' keyword

Brett Cannon brett at python.org
Wed Aug 27 20:19:43 CEST 2008


On Wed, Aug 27, 2008 at 9:51 AM, Tarek Ziadé <ziade.tarek at gmail.com> wrote:
> Hello
>
> There's a pattern I am doing all the time: filtering out some elements of a
> list, and cleaning them in the same move.
>
> For example, if I have a multi line text, where I want to:
>
> - keep non empty lines
> - clean non empty lines
>
> I am doing:
>
>     >>> text = """
>     ... this is a multi-line text\t
>     ...
>     ... \t\twith
>     ...
>     ... muliple lines."""
>
>     >>> [l.strip() for l in text.split('\n') if l.strip() != '']
>     ['this is a multi-line text', 'with', 'muliple lines.']
>
> It is not optimal, because I call strip() twice. I could use ifilter then
> imap or even use a real loop, but I
> want my simple, concise, list comprehension !  And I couldn't find a simple
> way to express it.
>
> The pattern can be generically resumed like this :
>
>    [transform(e) for e in seq if some_test(transform(e))]
>
> So what about using the 'as' keyword to extend lists comprehensions, and
> to avoid calling transform() twice ?
>

Not worth it since while you might want your "simple. concise list
comprehension", listcomps are not meant to generalize for all possible
situations in 'for' loops that can lead to a new list. Is it really
that much harder to write::

 list_ = []
 for line in text.splitlines():
   line = line.strip():
   if line:
     list_.append(line)

?

And if you really want your one-liner, you can avoid your duplicate
call to str.strip() in two different ways::

  [line.strip() for line in text.splitlines() if line and not line.isspace()]

or::

  filter(None, (line.strip() for line in text.splitlines()))

I don't see enough benefit to clutter listcomps with more syntax and
to provide another alternative to this pattern to add to the multiple
ones that already exist.

-Brett


More information about the Python-ideas mailing list