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