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