Write Pythonic Code Like a Seasoned Developer Transcripts
Chapter: Generators and Collections
Lecture: Inline generators via expressions
0:01 Let's continue our exploration of generators, we saw that we can create generator functions using the yield keyword,
0:07 we saw Python 3.3 added "yield from" to work with recursive generators and things like that - combining generators,
0:15 those were all functions, so we were able to transform the way the function worked but what about loops? What about things that are smaller,
0:24 little bits of code like what we have on the screen here, we've got some kind of iterable set called measurements,
0:30 we want to loop over it and we want to find all the ones that have some value over 70, we want to gather those up, so just like the drawbacks
0:38 our Fibonacci sequence where we pass the limit had before, this loop has similar problem, but the yield keyword won't help us, so let's see what will.
0:48 So here we have some code, we've created a named tuple, named Measurement, it's got an id, an x y coordinate and a value.
0:54 So think of this like a 3 by 3 grid, here where we have numbers or measurements like temperature or something around there.
1:02 So if we want to find all the locations that have some kind of high value or actually just look at what their measurements were,
1:09 we could go through like this, we could write a loop, first we could create a list to gather the measurements,
1:13 the high values, we loop over them, we do some kind of test and we add them up. All right, so that's OK, but it's not great.
1:21 However, let's just look at the rest of the app really quickly before we are done,
1:24 we are going to come up with this, these numbers in a variety of ways, we want to print them all out here,
1:29 so if we just run it you can see here is the ones we got through the loop, so I am calling this C-style but it's really any procedural programming way
1:37 and of course this blocks while this runs, now we can come down here we can take this code and we can do something a little bit different,
1:43 we can create what's called a list comprehension, the result is going to be exactly the same, the execution also will be basically exactly the same,
1:51 but we can take this and more or less inline what we have here. Now it looks like you are going to start out and we are just going to define a list,
1:59 but what in fact what we are going to do is we are going to define this thing called the comprehension that will loop over values and build up a list.
2:05 So the first thing you put is the values that are going to go onto the list, you have to imagine in the next statement,
2:11 the next line you are going to have some kind of variables, so I am going to say "m" again and the "m" is going to have a value,
2:16 I'll say for "m in measurements", just like above, and we'll say "if m.value is greater than or equal to 70",
2:24 so high measurements are 1 to high measurements 2 are the same, this is more declarative, so this is pretty cool
2:30 but they both sort of block and build this list, so in a lot of ways they are very similar,
2:34 the benefit here is this can be passed as part of an expression, whereas this is like separate code suite that you have to stop and then run,
2:42 you couldn't like pass this as an argument to a method, but like I say: "This you can, you can compose them and so on."
2:52 So let's see the results are the same, of course they are, excellent, so this executes and turns into a list but we talked about the generators,
3:00 that let us only pull out the items as we pull or we iterate over the generator.
3:06 So that's really cool, now we can do basically the same thing over here,
3:11 if you have square braces that means a list comprehension execute and return a list.
3:15 If you have parenthesis but you put basically the same thing inside, you create a generator that you can then iterate over,
3:22 this is just like writing a method with the yield keyword. So, if we just try to print out high measurements gen,
3:30 you'll see that we actually just get a generator, not a bunch of values because they hasn't actually executed, hasn't pulled on it.
3:37 So, in order to actually display the results we do this, wrap it in a list, make it generate something that we can then print and then there it is,
3:45 these list comprehensions are cool, there is other types of comprehensions as well,
3:50 all right, the generators, the yield, and that's most interesting I suppose, but we can also create a dictionary suppose
3:56 instead of just having the values, I'd like to say "given an id of a measurement, what is its value?", so we can come down here,
4:04 we can do something like this, or so, but instead of just passing the value here, I will say "key:value", so I would say "m.id:m.value".
4:14 Now if I run that, you can see here is the id value and id, here is some crazy id value is 73, but it is these values that you can look them up now
4:24 by key, not super helpful when you have 4 values or 5 whatever that is, but if you had hundreds of thousands, we saw how amazing that could be,
4:32 so this actually generates a dictionary because it's "key:value" for item in some set. Well, for item in some collection.
4:40 Now we can also create just the distinct values if you look down here you'll notice 90 is repeated 3 times
4:46 and if we just want to know what are the actual measurements, like was there a measurement of 90, was there a measurement of 73, and so on,
4:53 the ideal structure for that would be set. So we can use almost the same syntax as the dictionary comprehension here,
5:02 but instead of saying "key:value" we just put an item here, and if we use curly braces, and one value - not a "key:value" - that becomes a set.
5:12 And of course, the set is distinct items, so here is a wide variety of ways to replace standard C-style looping and gathering behavior into lists,
5:26 replace it with the generators, replace it with dictionaries and replace it with sets, all of these constructs are highly Pythonic and used often
5:36 especially when you are creating these pipelines and passing one to the next. All right, let's look at the core concept here, as a graphic.
5:44 So we saw we have our direct loop style or C-procedural style code create a list,
5:49 loop over a bunch of items, if they match some test we add them to our list. But, just like taking this type of algorithm and replacing it with yield
5:57 worked really well in a function, we can do the same thing with loops inline using generator expressions.
6:04 So, it's much of the same mechanics but the execution is vastly different so we say parenthesis for generator and then the value we want to get
6:13 and then we loop over the item with the "for...in" loop and then we do a test with an "if" clause, there you have it,
6:19 these generators are super useful, study them, you use them in a lot of places.