I happened to find myself having a basic filtering need: I have a list and I have to filter it by an attribute of the items.
My code looked like this:
my_list = [x for x in my_list if x.attribute == value]
But then I thought, wouldn't it be better to write it like this?
my_list = filter(lambda x: x.attribute == value, my_list)
It's more readable, and if needed for performance the lambda could be taken out to gain something.
Question is: are there any caveats in using the second way? Any performance difference? Am I missing the Pythonic Way™ entirely and should do it in yet another way (such as using itemgetter instead of the lambda)?
I find the second way more readable. It tells you exactly what the intention is: filter the list.
PS: do not use 'list' as a variable name
generally
filter
is slightly faster if using a builtin function.I would expect the list comprehension to be slightly faster in your case
This is a somewhat religious issue in Python. Even though Guido considered removing
map
,filter
andreduce
from Python 3, there was enough of a backlash that in the end onlyreduce
was moved from built-ins to functools.reduce.Personally I find list comprehensions easier to read. It is more explicit what is happening from the expression
[i for i in list if i.attribute == value]
as all the behaviour is on the surface not inside the filter function.I would not worry too much about the performance difference between the two approaches as it is marginal. I would really only optimise this if it proved to be the bottleneck in your application which is unlikely.
Also since the BDFL wanted
filter
gone from the language then surely that automatically makes list comprehensions more Pythonic ;-)Here's a short piece I use when I need to filter on something after the list comprehension. Just a combination of filter, lambda, and lists (otherwise known as the loyalty of a cat and the cleanliness of a dog).
In this case I'm reading a file, stripping out blank lines, commented out lines, and anything after a comment on a line:
In addition to the accepted answer, there is a corner case when you should use filter instead of a list comprehension. If the list is unhashable you cannot directly process it with a list comprehension. A real world example is if you use
pyodbc
to read results from a database. ThefetchAll()
results fromcursor
is an unhashable list. In this situation, to directly manipulating on the returned results, filter should be used:If you use list comprehension here you will get the error:
Curiously on Python 3, I see filter performing faster than list comprehensions.
I always thought that the list comprehensions would be more performant. Something like: [name for name in brand_names_db if name is not None] The bytecode generated is a bit better.
But they are actually slower: