I would not say that one is "better" or "worse" than the other, in reality both in performance and in conciseness the two forms are quite similar. The only thing that changes is the style of programming.
Imperative style :
impares = []
for i in range(1000):
if i % 2:
impares.append(i)
Functional style ( filter
):
impares = filter(lambda i: i % 2, range(1000)) # Python 2
impares = list(filter(lambda i: i % 2, range(1000))) # Python 3
Declarative style (list understanding):
impares = [i for i in range(1000) if i % 2]
All three forms are legible and should have similar performance. The imperative style is less concise, so I would only use it when the test expression was more complex (which would make a single lambda become too large, requiring an auxiliary function to keep it readable).
Personally, I find list understanding more "light-hearted," so I never write code using filter
(mostly filter
+ lambda
).
Regarding efficiency issues pointed out by sergiopereira , in fact filter
and list comprehensions create a new list, sometimes unnecessarily, which increases memory consumption. Since ifilter
, generating expressions and generators do not create or compute anything before it's time to actually use the results (and do not create persistent lists in memory).
Mandatory style generator:
def impar(elems):
for i in elems:
if i % 2:
yield i
for x in impar(range(1000)):
...
Functional style ( ifilter
):
for x in ifilter(lambda i: i % 2, range(1000)): # Python 2
...
for x in filter(lambda i: i % 2, range(1000)): # Python 3
...
Declarative style (generating expression):
for x in (i for i in range(1000) if i % 2):
...