5

Often when working with lists in Python, I end up wanting to simply filter out items from a list.

numbers = [5, 1, 4, 2, 7, 4]
big_nums = [num for num in numbers if num > 2]

To me this seems unnecessarily verbose. I have to define and use num in two separate statements (num for num ...), even though I don't do any operation on num.

I tried [num in numbers if num > 2], but python throws a SyntaxError with this.

Is there a more concise way of doing this in Python?

Edit:

My question is if there is a better way to do what I'm trying to do in Python. There are many times where there's been a construct in Python I didn't know about, but which made my code better and more readable.

I am not asking about performance tradeoffs between filter and list comprehension. I have no problem with list comprehension, but I also had no problem with building lists with standard for loops before I learned about list comprehension.

Community
  • 1
  • 1
jpyams
  • 4,030
  • 9
  • 41
  • 66
  • 2
    This seems like a code golf question, not a practical one, Python code is meant to be readable – Chris_Rands Sep 29 '17 at 15:43
  • 1
    `[num in numbers if num > 2]` makes it seem like you were trying to use a ternary expression (`x if y else z`) that contained an `in` expression and you just forgot the else-clause – Edward Minnix Sep 29 '17 at 15:43
  • I don't see a single thing wrong with that list comprehension. – cs95 Sep 29 '17 at 15:46
  • 1
    Note: the dupe will answer your question and much more. A simple "list comprehension alternative" google search would've turned that up as the first result. – cs95 Sep 29 '17 at 15:50
  • 3
    FWIW, if `numbers` were a 1D Numpy array you could do `numbers[numbers>2]` – PM 2Ring Sep 29 '17 at 15:51
  • @cᴏʟᴅsᴘᴇᴇᴅ The [dupe](https://stackoverflow.com/q/3013449) is informative, but it does not answer my question. I'm guessing the answer to my question is 'no', but my question is not the same as the suggested dupe (see my edit) – jpyams Sep 29 '17 at 17:11
  • 1
    "There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch." ;) – PM 2Ring Sep 30 '17 at 06:51
  • @PM2Ring Good point, so this question is for those of us who aren't Dutch and need a little help – jpyams Sep 30 '17 at 11:31
  • Fair enough. :) The "one obvious way" principal isn't as strict as it used to be (eg we now have several ways to format strings), but generally, if there's an obvious way it's probably better to use it than to search for obscure alternatives, since the obvious way is probably easier to understand & more readable. OTOH, "practicality beats purity"... – PM 2Ring Sep 30 '17 at 11:41

1 Answers1

9

Well, you could use filter, it's slower and not as readable but you don't need the for:

list(filter(lambda x: x > 2, numbers))

or:

list(filter((2).__lt__, numbers))

However using magic methods like this is fragile, this will only work if the list only contains integers. As Chris_Rands pointed out you normally use operator.lt instead:

from functools import partial
from operator import lt
list(filter(partial(lt, 2), numbers))

That would also work if the list contains other numeric types except int.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • 6
    Nice use of `__lt__`! +1 – Ajax1234 Sep 29 '17 at 15:40
  • 3
    and probably faster too because no lambda – Jean-François Fabre Sep 29 '17 at 15:41
  • 1
    probably importing `lt` from operator would be more 'pythonic'? – Chris_Rands Sep 29 '17 at 15:45
  • 1
    What Jean-François said. Also, you could use splat unpacking instead of calling the `list` constructor: `[*filter((2).__lt__, numbers)]`. But I agree that the standard list comp way is better, even if the repetition is slightly annoying. – PM 2Ring Sep 29 '17 at 15:45
  • 3
    @Chris_Rands Maybe, since directly calling dunder methods is generally frowned upon; OTOH, there are occasions where it makes sense to call a dunder method directly, and IMHO this is one of them. But of course, it's even more Pythonic to just use the standard list comp syntax that the OP is complaining about. ;) – PM 2Ring Sep 29 '17 at 15:47