- In the proceeding video, we began to introduce the concept
of list comprehensions in Python.
In this video,
we're going to talk about generator expressions.
Which look almost identical to list comprehensions.
The only difference visually
is that list comprehensions
are defined in square brackets
and generator expressions
are defined in parenthesis as you'll see momentarily.
Now there are a couple of other differences
between list comprehensions and generator expressions.
List comprehensions are what we call greedy expressions,
they have to evaluate immediately
because their job is to immediately
produce a list containing values
as specified in the comprehension.
On the other hand there's lots
of functional style programming techniques
that use what's known as lazy evaluation.
Where values get produced on demand as needed
or where values only get produced
once you begin to execute
the code that implements
the functional style programming technique.
Generator expressions are on demand expressions.
They produce one value at a time,
as that value gets asked for somewhere in your program.
And because of that
they can actually significantly improve performance
and reduce memory consumption in an application.
So for example if were going to use a list comprehension
to produce a one million element list,
I would have to create that one million element list
immediately and all of that memory would be occupied,
to store the actual elements of the list.
On the other hand if I create a generator expression
for one million elements,
I can ask for one element at a time,
do something with that
and then move on and thus tremendously reduce
the amount of memory that's required for processing
those one million elements.
In fact I could have a billion element generator
and maybe my program only asks for ten elements,
so I never wind up processing most of the elements
that the generator is capable of producing
and in the case of a list comprehension,
I would have to produce all one billion elements
in advance before I could then use that list of elements
and do something with it in the program.
So generator expressions can be a really handy
technique and they're just one of several different
techniques that are capable of producing values on demand
in the Python programming language.
So let's go ahead
and take a look at a basic generator expression,
so I'm gonna switch back over to my terminal window here.
And for the purpose of this demonstration
will define a list called numbers
with a bunch of integers in a kind of random order here.
Some of them of course are positive and some are negative.
And we're going to create a little four loop here
that's going to use a generator expression to pick off
the odd values and just display them.
Now, I'll talk more about generator expressions
after this as well.
So this expression right here looks very much
like the list comprehensions we were doing
in the proceeding video but notice
it has parenthesis around it, rather than square brackets.
If I put square brackets here, this,
it would be a list comprehension
and it would have to first evaluate in its entirety
to create the entire list.
Only then would the four loop be able
to walk through all the elements within that list
and then do whatever the four loop
says to do in the body here.
Now. If it's a generator expression
the four loop can basically ask the expression
to give me the next item in the sequence
during each ideration of the loop
and then print out the corresponding value.
So, here you can see
we're getting the square of X for each value of X
in the numbers list
where X divided by 2,
gives a remainder that's not equal to 0.
So basically, if it's equal to 0, it's even.
If it's not equal to 0 then it's odd
and so this is going to pick off the odd values
in that list and only give me the squares of the odd values.
So, let's go ahead and execute that loop
and we can see 10 was ignored but 3 was squared.
7 was squared to give us 49, 1 squared still gives us 1 ,
9 squared gives us 81, 4 was ignored, 2 was ignored,
8 was ignored, 5 squared gave us 25 and 6 was ignored.
So we filtered out half of the elements
in this particular example
and produced the squares of the other half of the elements
and in terms of performance here
because we're only dealing
with ten elements in the first place.
There's no major difference in performance
but if we were dealing with millions of elements
then you would have a massive difference in performance
between creating a list of that size,
the memory that it takes
verses using a generator expression.
Now, just to show you that a generator expression
is not actually creating a list.
I'm going to take this same expression
and assign it to a variable.
I'll call it square of odds, here.
And if I now go and evaluate
square of odds.
You can see that it tells me this thing
is actually a generator object,
based on a generator expression.
So this is just a notation
that tells you that this thing,
is in fact an object in memory.