This is a list comprehension that allows you to define one list in terms of another list and is reminiscent of set notation from mathematics. The elegance, simplicity, and power of this notation makes it, in my opinion, the best feature of Python. Now what does it mean to be a best feature of a programming language?
To me, it's a feature that makes you fall in love with the language and a feature that makes you enjoy programming in a language for many years. So the basic notation is a for loop over some input list nums and a function like f of x that computes something for each element x in nums.
In addition, there's a filter conditional like if g of x, some function, some expression that filters the elements of nums and only keeps the ones that pass this conditional. Let's look at an example input list nums one two three four. The list comprehension squares each element of nums so x times x for x in nums.
So that creates a list that contains one four nine and sixteen. Simple, beautiful. And now to add a filter to keep just the even numbers we can add into the filter conditional of the list comprehension x modula two equals zero. And then the result is the squaring of the elements that pass the filter which is four and sixteen.
Now some would argue that you can achieve the same kind of results with for loops or more direct comparison is the map and filter functions which are also available in Python. So what would that look like to square each element in the list? You can have a lambda function that does the squaring and a map that applies that lambda function to each element of nums.
That's the second line in the code here. And the third line you can add a filter to that. So first apply a filter with a lambda function that does the modula two equals zero conditional. And then on top of that on the elements that pass the filter you again do the map function of the lambda that squares each element.
Now I believe this is also beautiful and powerful notation but to me it's not nearly as elegant and Pythonic and readable as the list comprehension notation. Now I already did a video on the most controversial Python feature which in my opinion is the walrus operator. It comes into play nicely with list comprehensions.
Now if we take some difficult to compute function like fibo here which computes the nth element of the Fibonacci sequence. The one line ternary operator recursive implementation of the function written by me untested. I'll leave it to you as homework to test if this actually works. And I threw it in there to give a shout out to two other things I enjoy which is recursion and the ternary operator.
The if else notation of which in Python I think is another beautiful design choice that makes an otherwise cryptic looking ternary operator actually readable to our human brains. And so if we take then another definition of nums that goes from one to six. We can create a basic list comprehension that applies the fibo function to each element of nums resulting in the familiar Fibonacci sequence of 1 1 2 3 5 8.
Now if we wanted to also add a conditional which is where the walrus operator comes in. We can compute fibo x and assign it to the variable y via the walrus operators assignment expression and then do the modules two equals zero check to keep just the even elements of the Fibonacci sequence.
And then in the actual output of the list comprehension we can just use the variable y as opposed to re-computing the fibo function. So the result of this list comprehension that uses the walrus operator is two and eight. So list comprehension actually creates a list objects computes all the elements in the list and stores the entire list of memory while the generator expression stores just the iterable object and computes every element in the list one at a time as it's being queried.
So for most people the list comprehension is probably the default choice. It's used when the size of the list is not crazy large. Especially when you want to reiterate over the list multiple times. It is faster than generator expressions depending on the context. It could be two to three times faster.
So speed is essential you want to use these. And if you need different list methods like especially the slicing notation you should be using list comprehension. On the other hand you should use generator expressions when the range of the sequence is large or infinite. Or if you want to construct iteratable generator objects which are great to impress your friends with.
I should mention I'm really grateful for the sponsors that support these videos and the podcast. In this case 8sleep. So if you enjoy these click the links in the description to get a discount and to support my efforts. Thanks for listening and remember try to learn something new every day.
you you you you you you you