realpython / python-guide

Python best practices guidebook, written for humans.
https://docs.python-guide.org
Other
28.34k stars 5.83k forks source link

Are list comprehensions pythonic? #167

Closed pbdeuchler closed 10 years ago

pbdeuchler commented 12 years ago

While I'd agree list comprehensions are generally nice, and make one feel very clever when using them, are they necessarily more pythonic than their counterparts?

In your section "Short Ways to Manipulate Lists" you call the following code "Bad",

# Filter elements greater than 4
a = [3, 4, 5]
b = []
for i in a:
    if i > 4:
        b.append(i)

and the following list comprehensions "Good",

b = [i for i in a if i > 4]
b = filter(lambda x: x > 4, a)

The section goes on to include more examples.

I would argue that calling the simpler code "Bad" simply because it takes up more space and doesn't include lambdas/one liners gives the wrong message, especially to beginners. Following the Zen of Python, specifically "Explicit is better than implicit", "Simple is better than complex", and "Readability counts" the list comprehensions could be qualified as less pythonic than the more explicit nested conditional clauses. However, this could be refuted by "Flat is better than nested".

I could be wrong, just thought I would bring it up.

robert-wallis commented 12 years ago

PEP 202 says:

List comprehensions provide a more concise way to create lists in situations where map() and filter() and/or nested loops would currently be used. http://www.python.org/dev/peps/pep-0202/

Interestingly GVR says using map with lambda as one of his "regrets" and to use a list comprehension instead. Then in the very next section he says a for loop is more clear than reduce().

• map(), filter() – using a Python function here is slow – list comprehensions do the same thing better • reduce() – nobody uses it, few understand it – a for loop is clearer & (usually) faster http://www.python.org/doc/essays/ppt/regrets/PythonRegrets.pdf

Also Guido said:

"It has been argued that the real problem here is that Python’s lambda notation is too verbose, and that a more concise notation for anonymous functions would make map() more attractive. Personally, I disagree—I find the list comprehension notation much easier to read than the functional notation, especially as the complexity of the expression to be mapped increases. In addition, the list comprehension executes much faster than the solution using map and lambda. This is because calling a lambda function creates a new stack frame while the expression in the list comprehension is evaluated without creating a new stack frame." http://python-history.blogspot.com/2010/06/from-list-comprehensions-to-generator.html

Timing map with a function vs map with a lambda: http://stackoverflow.com/questions/1247486/python-list-comprehension-vs-map

samueljohn commented 12 years ago

I agree with @robert-wallis. I love list comprehensions. So beautiful. And they are indeed faster. Nested list comprehensions become harder to read though.

The most simple list comprehension does read more difficult that a slightly complexer one:

b = [ i*i for i in my_list if i > 4 ]
jabagawee commented 12 years ago

Going off of what @robert-wallis said, I think we should move the filter() call to the "bad" section. It seems that the general consensus in Python is that list comprehensions are good and overly verbose for loops and filter/map calls are bad.

kennethreitz commented 12 years ago

I use map every day :)

xr09 commented 11 years ago

I think list comprehension (as other functional sides of Python) are not the most "n00b" friendly feature, but once you get them you will migrate any old code to use them, so I would stick to teach them as a good thing, a little less easy to grasp but definitely good.

rawrgulmuffins commented 11 years ago

The relevant part starts at 2:55. You should watch the whole video regardless. https://www.youtube.com/watch?v=OSGv2VnC0go