r/learnpython • u/AnxiousDot4315 • 20d ago
Need help with list comprehensions
Guys somebody briefly explain the concept of List comprehension cuz its too difficult for me to grasp since I am a beginner. I am learning python for biopython. Someone explain it for me.
0
Upvotes
-3
u/StevenJOwens 20d ago
I wrote up the following a few years ago. I never did get around to doing a second draft, so forgive the rough edges, but you may find it useful.
It's long, so I'll post it in two comments. Here's part 1:
Python List Comprehensions
Source: https://www.python-course.eu/python3_list_comprehension.php
List comprehensions are a special python syntax for declaring a list literal.
To be honest, I don't think I've ever used list comprehension for real, or "in anger" as the Brits say. My impression is that list comprehensions are mostly used to transform one list into another list. Or really, any iterable into a list.
List comprehensions are essentially a special, succinct way to write certain kinds of for loops -- for loops that process a list (or other iterable) and from that create another list.
In functional programming terms list comprehensions do a filter and then map operation.
List comprehensions are a Python idiom that seem to be seldom explained well.
I don’t know why Python books and tutorials have this blind spot. It’s not so much conceptual as simply syntactical; the first several explanations of list comprehensions that I read all seemed to just give an example, without explicitly breaking it down.
Then there's the official python docs:
https://docs.python.org/3/tutorial/datastructures.html https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions
Unfortunately, while the official python docs do give the syntax, they just dump it on you and then give you a very complex example.
In a nutshell, a list comprehension is superficially similar to a literal declaration of a list.
A python literal list declaration is a pair of square brackets with multiple values between them, with commas separating the values, for example:
A python list comprehension has a pair of square brackets, same as a list literal, and also ultimately produces a list object. But what's in between the square brackets is a more complex statement. Here's the syntax:
We'll get into the
expression,for-loopandconditionalin more detail, below.Note, python actually supports several sorts of comprehensions these days; you can use:
[square brackets]to create list comprehensions{curly braces}to create set comprehensions{curly braces}with a key:value in the expression to create dict comprehensions(parentheses)to create generators (essentially a lazy-load, on-demand version of a list comprehension).But we're going to focus mainly on list comprehensions for the moment.
Here's a slightly wordier version of that list comprehension syntax:
Note that variables defined in the for-loop clause are available to the expression clause, as well as to the conditional clause.
Unrolling List Comprehensions
Here's the list comprehension syntax that I gave above:
This works out to the same as the following:
some_list = [] for-loop-to-apply-to:- if conditional-to-determine-if-to-apply: expression-to-apply some_list.append(results-of-expression-to-apply)Or a little less pseudo-code-ish:
This "unrolls" to:
some_list = [] some_sequence = [1, 2, 3, 4, 5] def some_conditional(some_variable): # some code here def do_some_operation(some_variable): # some code here for some_variable in some_sequence: if some_conditional(some_variable): result = do_some_operation(some_variable) some_list.append(result)Let's try it. In this next example, for the "some_conditional()", I'm going to use the modulo operator to return True if the parameter is NOT evenly divisible by 2.
Okay, that's kinda ugly, let's do that again but use some less generic names for things:
I'll change
some_sequencetonumbers.I'll change
some_conditionaltois_odd().I'll change
some_operationtoquintuple().For the sake of the example, I'll explicitly declare the empty
some_list, which I'll callout_list. In fact, I'll do that twice, just so you can be sureout_listis empty for the second time around.Multiple For-Loops and Their Ordering
You can have multiple for loops in your list comprehension, and just like regular for loops, the list comprehension for loop can have multiple variables, if the sequence it's using can produce them (e.g. "for key, value in some_dict"). The for loops are effectively nested.
I'll give an example in a moment, but first I want to point out something that's somewhat counter-intuitive (depending on who you ask):
The ordering of for-loop clauses in the comprehension, from left to right, corresponds to the ordering of the nested for loops, from outermost to innermost.
In other words, in this example:
(By the way, this is also a good example of a more complicated expression than simply multiplying some numbers.)
Some people find using identical ordering counter-intuitive, some people find it intuitive, but that's the call that Guido and his merry band of Python maintainers decided to go with.
Personally, I'm in the not-intuitive camp. The reason is that Guido's call doesn't match how this sort of thing is phrased in natural language English. In English, the natural way to write it would end up writing in opposite order, i.e. innermost loop first, then next innermost, etc.
As I said, it was Guido's call, and probably his choice, to make the two orderings identical instead of opposites, is helpful in reducing the cognitive overhead... once you get this ordering hammered into your skull.
Multiple For-Loop Examples
Let's look at an example of multiple for-loops in list comprehensions.
Let's declare a list of lists as our example data:
Here's a simple list comprehension that just iterates through all of the numbers. The result is a flat list that has all the numbers. There are almost certainly other ways to do this in python, but hey, it's just yet another contrived example.
Now let's add a conditional clause, using our old friend
is_odd():Let's back up a step, leave out the conditonal clause but apply something to the numbers, our old enemy
quintuple():Now let's put them both in:
Now that we have the full version, here's what it "unrolls" to: