Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #108207 > unrolled thread

Re: Pylint prefers list comprehension over filter...

Started byStephen Hansen <me@ixokai.io>
First post2016-05-05 18:37 -0700
Last post2016-05-07 12:37 -0700
Articles 8 — 6 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Pylint prefers list comprehension over filter... Stephen Hansen <me@ixokai.io> - 2016-05-05 18:37 -0700
    Re: Pylint prefers list comprehension over filter... Dan Sommers <dan@tombstonezero.net> - 2016-05-06 02:46 +0000
      Re: Pylint prefers list comprehension over filter... Chris Angelico <rosuav@gmail.com> - 2016-05-06 12:55 +1000
      Re: Pylint prefers list comprehension over filter... Stephen Hansen <me+python@ixokai.io> - 2016-05-05 19:57 -0700
        Re: Pylint prefers list comprehension over filter... Steven D'Aprano <steve@pearwood.info> - 2016-05-06 22:42 +1000
      Re: Pylint prefers list comprehension over filter... Dan Sommers <dan@tombstonezero.net> - 2016-05-06 03:07 +0000
        Re: Pylint prefers list comprehension over filter... Chris Angelico <rosuav@gmail.com> - 2016-05-06 13:18 +1000
      Re: Pylint prefers list comprehension over filter... Christopher Reimer <christopher_reimer@icloud.com> - 2016-05-07 12:37 -0700

#108207 — Re: Pylint prefers list comprehension over filter...

FromStephen Hansen <me@ixokai.io>
Date2016-05-05 18:37 -0700
SubjectRe: Pylint prefers list comprehension over filter...
Message-ID<mailman.422.1462498634.32212.python-list@python.org>
On Thu, May 5, 2016, at 06:26 PM, Christopher Reimer wrote:
> Which is one is correct (Pythonic)? Or does it matter?

First, pylint is somewhat opinionated, and its default options shouldn't
be taken as gospel. There's no correct: filter is fine.

That said, the general consensus is, I believe, that list comprehensions
are good, and using them is great.

In your case, though, I would not use a list comprehension. I'd use a
generator comprehension. It looks almost identical:

    ''.join(x for x in string if x.isupper())

The difference is, both filter and your list comprehension *build a
list* which is not needed, and wasteful. The above skips building a
list, instead returning a generator, and join pulls items out of it one
at a time as it uses them. No needlessly creating a list only to use it
and discard it.

-- 
Stephen Hansen
  m e @ i x o k a i  . i o

[toc] | [next] | [standalone]


#108209

FromDan Sommers <dan@tombstonezero.net>
Date2016-05-06 02:46 +0000
Message-ID<ngh0hu$4og$1@dont-email.me>
In reply to#108207
On Thu, 05 May 2016 18:37:11 -0700, Stephen Hansen wrote:

>     ''.join(x for x in string if x.isupper())

> The difference is, both filter and your list comprehension *build a
> list* which is not needed, and wasteful. The above skips building a
> list, instead returning a generator ...

filter used to build a list, but now it doesn't (where "used to" means
Python 2.7 and "now" means Python 3.5; I'm too lazy to track down the
exact point(s) at which it changed):

    Python 2.7.11+ (default, Apr 17 2016, 14:00:29) 
    [GCC 5.3.1 20160409] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> filter(lambda x:x+1, [1, 2, 3, 4])
    [1, 2, 3, 4]

    Python 3.5.1+ (default, Apr 17 2016, 16:14:06) 
    [GCC 5.3.1 20160409] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> filter(lambda x:x+1, [1, 2, 3, 4])
    <filter object at 0x7f26a9ef3320>

[toc] | [prev] | [next] | [standalone]


#108211

FromChris Angelico <rosuav@gmail.com>
Date2016-05-06 12:55 +1000
Message-ID<mailman.425.1462503307.32212.python-list@python.org>
In reply to#108209
On Fri, May 6, 2016 at 12:46 PM, Dan Sommers <dan@tombstonezero.net> wrote:
> filter used to build a list, but now it doesn't (where "used to" means
> Python 2.7 and "now" means Python 3.5; I'm too lazy to track down the
> exact point(s) at which it changed):
>
>     Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
>     [GCC 5.3.1 20160409] on linux2
>     Type "help", "copyright", "credits" or "license" for more information.
>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>     [1, 2, 3, 4]
>
>     Python 3.5.1+ (default, Apr 17 2016, 16:14:06)
>     [GCC 5.3.1 20160409] on linux
>     Type "help", "copyright", "credits" or "license" for more information.
>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>     <filter object at 0x7f26a9ef3320>

Most of these kinds of changes happened in 3.0, where
backward-incompatible changes were accepted. A whole bunch of things
stopped returning lists and started returning lazy iterables - range,
filter/map, dict.keys(), etc - because most of the time, they're
iterated over once and then dropped.

ChrisA

[toc] | [prev] | [next] | [standalone]


#108213

FromStephen Hansen <me+python@ixokai.io>
Date2016-05-05 19:57 -0700
Message-ID<mailman.426.1462503449.32212.python-list@python.org>
In reply to#108209
On Thu, May 5, 2016, at 07:46 PM, Dan Sommers wrote:
> On Thu, 05 May 2016 18:37:11 -0700, Stephen Hansen wrote:
> 
> >     ''.join(x for x in string if x.isupper())
> 
> > The difference is, both filter and your list comprehension *build a
> > list* which is not needed, and wasteful. The above skips building a
> > list, instead returning a generator ...
> 
> filter used to build a list, but now it doesn't (where "used to" means
> Python 2.7 and "now" means Python 3.5; I'm too lazy to track down the
> exact point(s) at which it changed):

Oh, didn't know that. Then again the OP was converting the output of
filter *into* a list, which wasted a list either way.

-- 
Stephen Hansen
  m e @ i x o k a i . i o

[toc] | [prev] | [next] | [standalone]


#108223

FromSteven D'Aprano <steve@pearwood.info>
Date2016-05-06 22:42 +1000
Message-ID<572c9155$0$1601$c3e8da3$5496439d@news.astraweb.com>
In reply to#108213
On Fri, 6 May 2016 12:57 pm, Stephen Hansen wrote:

> On Thu, May 5, 2016, at 07:46 PM, Dan Sommers wrote:
>> On Thu, 05 May 2016 18:37:11 -0700, Stephen Hansen wrote:
>> 
>> >     ''.join(x for x in string if x.isupper())
>> 
>> > The difference is, both filter and your list comprehension *build a
>> > list* which is not needed, and wasteful. The above skips building a
>> > list, instead returning a generator ...
>> 
>> filter used to build a list, but now it doesn't (where "used to" means
>> Python 2.7 and "now" means Python 3.5; I'm too lazy to track down the
>> exact point(s) at which it changed):
> 
> Oh, didn't know that. Then again the OP was converting the output of
> filter *into* a list, which wasted a list either way.


In Python 2.7, run `from future_builtins import *` to get most of the Python
3 behaviour:


py> filter(None, [])
[]
py> from future_builtins import *
py> filter(None, [])
<itertools.ifilter object at 0xb7ee3e8c>



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#108214

FromDan Sommers <dan@tombstonezero.net>
Date2016-05-06 03:07 +0000
Message-ID<ngh1pb$4og$2@dont-email.me>
In reply to#108209
On Fri, 06 May 2016 02:46:22 +0000, Dan Sommers wrote:

>     Python 2.7.11+ (default, Apr 17 2016, 14:00:29) 
>     [GCC 5.3.1 20160409] on linux2
>     Type "help", "copyright", "credits" or "license" for more information.
>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>     [1, 2, 3, 4]
> 
>     Python 3.5.1+ (default, Apr 17 2016, 16:14:06) 
>     [GCC 5.3.1 20160409] on linux
>     Type "help", "copyright", "credits" or "license" for more information.
>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>     <filter object at 0x7f26a9ef3320>

Muphrey's Law strikes again.  That lambda function is obviously a
leftover from a call to *map* rather than a call to *filter*, but thanks
everyone for not laughing and pointing.

[toc] | [prev] | [next] | [standalone]


#108215

FromChris Angelico <rosuav@gmail.com>
Date2016-05-06 13:18 +1000
Message-ID<mailman.427.1462504727.32212.python-list@python.org>
In reply to#108214
On Fri, May 6, 2016 at 1:07 PM, Dan Sommers <dan@tombstonezero.net> wrote:
> On Fri, 06 May 2016 02:46:22 +0000, Dan Sommers wrote:
>
>>     Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
>>     [GCC 5.3.1 20160409] on linux2
>>     Type "help", "copyright", "credits" or "license" for more information.
>>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>>     [1, 2, 3, 4]
>>
>>     Python 3.5.1+ (default, Apr 17 2016, 16:14:06)
>>     [GCC 5.3.1 20160409] on linux
>>     Type "help", "copyright", "credits" or "license" for more information.
>>     >>> filter(lambda x:x+1, [1, 2, 3, 4])
>>     <filter object at 0x7f26a9ef3320>
>
> Muphrey's Law strikes again.  That lambda function is obviously a
> leftover from a call to *map* rather than a call to *filter*, but thanks
> everyone for not laughing and pointing.

Hey, maybe you wanted to filter out all the -1 results. Maybe you have
a search function that returns zero-based offsets, or -1 for "not
found". Seems reasonable! And "x+1" is way shorter than "x!=-1", which
means by definition that it's better.

ChrisA

[toc] | [prev] | [next] | [standalone]


#108289

FromChristopher Reimer <christopher_reimer@icloud.com>
Date2016-05-07 12:37 -0700
Message-ID<mailman.467.1462649844.32212.python-list@python.org>
In reply to#108209
On 5/5/2016 7:57 PM, Stephen Hansen wrote:
> On Thu, May 5, 2016, at 07:46 PM, Dan Sommers wrote:
>> On Thu, 05 May 2016 18:37:11 -0700, Stephen Hansen wrote:
>>
>>>      ''.join(x for x in string if x.isupper())
>>> The difference is, both filter and your list comprehension *build a
>>> list* which is not needed, and wasteful. The above skips building a
>>> list, instead returning a generator ...
>> filter used to build a list, but now it doesn't (where "used to" means
>> Python 2.7 and "now" means Python 3.5; I'm too lazy to track down the
>> exact point(s) at which it changed):
> Oh, didn't know that. Then again the OP was converting the output of
> filter *into* a list, which wasted a list either way.

My line of code was something I copied off the Internet and modified it 
until it did I exactly what I wanted it to do. That means that the many 
Python 2 code examples available on the Internet are using a redundant 
list operation with Python 3. Isn't that a "smell" that pylint should 
pick up on?

Thank you,

Chris R.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web