76

I have a line like this:

filter(lambda x: x == 1, [1, 1, 2])

Pylint is showing a warning:

W:  3: Used builtin function 'filter'

Why is that? is a list comprehension the recommended method?

Of course I can rewrite this like this:

[x for x in [1, 1, 2] if x == 1]

And I get no warnings, but I was wondering if there's a PEP for this?

igorgue
  • 17,884
  • 13
  • 37
  • 54
  • 1
    Funnily, pylint doesn't like when I use the builtin function `map`, but it doesn't like either when I import the `map` function from `cytoolz` to use this instead. – bli Jan 17 '17 at 17:21

4 Answers4

97

Pylint often chatters on about stuff it shouldn't. You can disable the warning in a .pylintrc file.

This page http://pylint-messages.wikidot.com/messages:w0141 indicates the problem is that filter and map have been superseded by list comprehensions.

A line like this in your pylintrc file will quiet the warning:

disable=W0141
Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 6
    I didn't know about it either. I ran pylint with the "-i y" flag to include the message number, then I Googled "pylint W0141", and that's what I found. – Ned Batchelder Aug 25 '10 at 19:37
  • 1
    @NedBatchelder: Thank you! You should eventually also add the header `[MESSAGES CONTROL]` (see [.pylintrc example](http://www.pymvpa.org/misc/pylintrc)) as somebody who just creates this file mgiht not know that this is necessary. – Martin Thoma Oct 24 '14 at 16:22
  • 3
    Consider disabling this by using the longer, more readable message name: `# pylint: disable=bad-builtin`. Or in the pylintrc: `[MESSAGES CONTROL] disable=bad-builtin`. It's more clear that just a warning number. – johntellsall Jun 17 '16 at 15:22
11

Why is that? is a list comprehension the recommended method?

List comprehension is recommended in the tutorial example, which states

it’s more concise and readable.

and by most answerers on SO's Python List Comprehension Vs. Map where it is

  1. more efficient to use list comprehension than filter if you are defining a lambda each time
  2. maybe more readable (and with similar efficiency) to use filter if the function is pre-defined
  3. necessary to use filter and map if you
    • map map,
    • curry map, or
    • use functional programming

TL;DR: use list comprehension in most cases

Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188
5

I ran into the same problem and could not figure out

why the built-in function `input' is bad. I you intend

to disable it:

pylint --bad-functions="[map,filter,apply]" YOUR_FILE_TO_CHECK_HERE

Once you like the settings:

pylint --bad-functions="[map,filter,apply]" --some-other-supercool-settings-of-yours
--generate-rcfile > test.rc

Verify that your settings are in the file, e.g.:

cat test.rc | grep -i YOUR_SETTING_HERE

After that you can use this file locally

pylint --rcfile test.rc --your-other-command-line-args ...

or even use it as your default rcfile. For this I kindly refer you to

pylint --long-help
benjamin
  • 2,185
  • 1
  • 14
  • 19
  • 4
    In python2, `input()` is evil because it does `eval(raw_input())`. You should always use `raw_input()`. In python3, `input()` has the desired behavior (always returns `str`). – mic_e Jan 11 '17 at 16:15
1

I've got the same warning on my project. I'm changing the source code to be py2/3 compatible, and pylint helps a lot.

Running pylint --py3k shows only errors about compatibility.

In python 2, if use filter, it returns a list:

>>> my_list = filter(lambda x: x == 1, [1, 1, 2])
>>> my_list
[1, 1]
>>> type(my_list)
<type 'list'>

But in python 3, filter and other similar methods (map, range, zip, ..) return a iterator, that is incompatible types and perhaps cause bugs in your code.

>>> my_list = filter(lambda x: x == 1, [1, 1, 2])
>>> my_list
<filter object at 0x10853ac50>
>>> type(my_list)
<class 'filter'>

To make your code python 2/3 compatible, I use a cheat sheet from python future site

To avoid this warning, you can use 4 approaches, that works on python 2 and 3:

1 - Using a list comprehension like you said.

2 - Using a list function, grant that return always is a materialized list, result is same on both python versions

>>> list(filter(lambda x: x == 1, [1, 1, 2]))
[1, 1]

3 - Using lfilter, that's a future package import. It always return a list, uses filter on py2, and list(filter(..) on py3. So, both pythons got the same behaviour and you got a cleaner syntax.

>>> from future.utils import lfilter
>>> lfilter(lambda x: x == 1, [1, 1, 2])
[1, 1]

4 - The best! Use filter always on a loop, this way pylint don't give warnings, and it have a nice performance boost on python 3.

>>> for number in filter(lambda x: x == 1, [1, 1, 2]):
>>>     print(number)
>>> 1
>>> 1

Always prefer functions that works on python 3, because python 2 will be retired soon.