1
00:00:05,580 --> 00:00:11,570
Alright so we left the last video with a challenge: to convert a nested for loop into a list comprehension.

2
00:00:11,740 --> 00:00:13,120
So let's go through the solution,

3
00:00:13,120 --> 00:00:14,640
one solution to that.

4
00:00:14,720 --> 00:00:17,370
So we're going to start on line 11, so times

5
00:00:17,650 --> 00:00:24,840
equals left square bracket, or left and right square brackets, in parentheses i comma space

6
00:00:24,850 --> 00:00:34,770
i times j, then a right parentheses, then we want for i in range, parentheses one comma space 11, closing

7
00:00:34,780 --> 00:00:41,750
parentheses, for j in range, parentheses 1 comma space 11.

8
00:00:42,040 --> 00:00:47,480
Then we've got our right closing, right parentheses and closing square bracket. Then on the next line

9
00:00:47,480 --> 00:00:51,510
we can print parentheses times.

10
00:00:51,640 --> 00:00:55,430
So once again that reads pretty much the same as the nested for loops.

11
00:00:55,430 --> 00:00:58,580
We run the program,

12
00:00:59,330 --> 00:01:05,269
and you can see that we're getting a list of tuples, very similar to the, or they should be identical to

13
00:01:05,269 --> 00:01:08,330
the first one you, left to right there.

14
00:01:10,530 --> 00:01:15,960
So obviously, here each tuple is containing the number from 1 to 10, with its product for values from 1

15
00:01:15,960 --> 00:01:16,890
to 10.

16
00:01:16,890 --> 00:01:22,350
Now if we wanted to print the same output as the nested for loops, just unpack the tuple when iterating over

17
00:01:22,350 --> 00:01:23,450
the list.

18
00:01:23,460 --> 00:01:26,210
So let's just do that, so we'll just close down the run window.

19
00:01:26,460 --> 00:01:30,470
We can just copy the output here and then we'll change it a bit.

20
00:01:30,480 --> 00:01:33,360
So I'm going to copy that, and we'll change it.

21
00:01:33,360 --> 00:01:42,500
So it's going to be for x comma space y in, then just a colon on the end.

22
00:01:43,890 --> 00:01:51,030
Then we can print x comma y. As it turns out I'll just delete that extra times there. Alright so lets just

23
00:01:51,030 --> 00:01:59,690
try running that, and you can see we got the same output now than from the original nested for loop example,

24
00:02:00,280 --> 00:02:01,370
the top of the file.

25
00:02:05,250 --> 00:02:07,410
OK, so that's the challenge completed. If you got the same results,

26
00:02:07,410 --> 00:02:08,910
congratulations.

27
00:02:08,910 --> 00:02:13,230
Now you may also have used a comprehension as the expression.

28
00:02:13,230 --> 00:02:21,360
So if I go back and just show you what I mean by that, you may have done it this way: then I'll paste that in line 17, then we'll say times

29
00:02:21,380 --> 00:02:28,890
2 equals, so you might have added two square brackets like we've used previously.

30
00:02:29,340 --> 00:02:32,040
Then add the right square bracket

31
00:02:32,040 --> 00:02:33,610
after the first range,

32
00:02:33,720 --> 00:02:40,620
so basically after here, after the right parentheses on the range, and print times two.

33
00:02:45,750 --> 00:02:50,720
A similar thing as you can see but, the structure's different though if you do it that way but of course the

34
00:02:51,140 --> 00:02:53,390
end result is still correct.

35
00:02:53,390 --> 00:02:55,430
We've got the output that we're,

36
00:02:55,610 --> 00:02:59,800
we've actually got it going through using nested comprehensions.

37
00:02:59,900 --> 00:03:04,690
Now if you want it to have been completely accurate, you should also have swapped i and j around.

38
00:03:04,820 --> 00:03:10,460
So the first loop is for j then the outer loop at the end is for i. Of course as they're both looping through

39
00:03:10,460 --> 00:03:13,520
exactly the same set of values it doesn't make any difference here.

40
00:03:14,000 --> 00:03:18,020
Alright so we've used a list comprehension here, which means it builds up a list containing all the

41
00:03:18,020 --> 00:03:19,100
values.

42
00:03:19,110 --> 00:03:23,340
Now that could use up a lot of memory, especially with very large ranges.

43
00:03:23,350 --> 00:03:28,270
Now if you intend to use the list again, then a list comprehension does make sense.

44
00:03:28,670 --> 00:03:34,470
And in our original solution, we could use the times list as often as necessary in the code.

45
00:03:34,630 --> 00:03:39,020
Now if you just want to iterate over the list as we're doing here, then a generator expression is probably

46
00:03:39,020 --> 00:03:41,780
more suitable than a list comprehension.

47
00:03:41,860 --> 00:03:44,740
Now generator expressions are very similar to write.

48
00:03:45,020 --> 00:03:48,470
We just replace the square brackets with parentheses.

49
00:03:48,500 --> 00:03:57,840
So if I go back and copy lines 14 and 15 again. I'm going to paste them in, see I'll put that up there to be consistent.

50
00:03:58,550 --> 00:04:01,320
So we've got here, the square bracket,

51
00:04:01,330 --> 00:04:04,280
I'm going to change that to a parentheses,

52
00:04:04,460 --> 00:04:11,990
then the second square bracket. Come down to the end here, and replace that with parentheses, and just

53
00:04:11,990 --> 00:04:18,589
run it to confirm it is actually working.

54
00:04:18,690 --> 00:04:20,860
And you can see we've got the same output there.

55
00:04:22,370 --> 00:04:28,400
But the difference here with this code is that it's a generator expression, and it isn't creating the entire

56
00:04:28,400 --> 00:04:29,630
list in memory.

57
00:04:29,630 --> 00:04:32,930
Now just like generators, and we saw those a few videos ago,

58
00:04:33,050 --> 00:04:39,080
generator expressions calculate the values as they're requested. The only value that exists is the one that's

59
00:04:39,080 --> 00:04:40,700
just been returned.

60
00:04:40,730 --> 00:04:46,470
Now bear that in mind and consider using a generator expression rather than a list comprehension,

61
00:04:46,520 --> 00:04:49,460
if you're not going to be using the list more than once.

62
00:04:49,550 --> 00:04:54,380
Now one thing that's currently unclear, is whether performance suffers when you use generator expressions

63
00:04:54,620 --> 00:04:56,510
rather than list comprehensions.

64
00:04:56,540 --> 00:05:02,970
Now Guido van Rossum said that they should both be as fast as each other in the blog post that I've linked to previously.

65
00:05:03,370 --> 00:05:06,860
However that was written quite a while ago and things may well have changed.

66
00:05:06,860 --> 00:05:10,880
And also he was only talking about the CPython implementations of Python.

67
00:05:10,880 --> 00:05:14,910
If you're using a different implementation, things may well be different.

68
00:05:15,350 --> 00:05:17,430
So that says, does performance suffer.

69
00:05:17,750 --> 00:05:23,100
Well I'm not going to tell you. Instead though, what we're going to do is look at how you can find out for yourself.

70
00:05:23,180 --> 00:05:29,210
Now Python has a timeit module in the standard library, and we can use that to compare the performance

71
00:05:29,480 --> 00:05:33,640
of different code snippets, and we'll start working on that in the next video.

72
00:05:33,920 --> 00:05:39,950
But before that, I promised that we'd use a nested comprehension to produce the list of destinations

73
00:05:39,950 --> 00:05:41,410
from an earlier challenge,

74
00:05:41,420 --> 00:05:42,810
that's Challenge 2.

75
00:05:42,860 --> 00:05:51,000
Now what I'm going to do, is go back to that Challenge 2 solution, that was compchallenge2. Alright so lets

76
00:05:51,020 --> 00:05:56,780
go ahead and do that, so actually what I'm going to do is do a file new, Python file,

77
00:05:56,790 --> 00:06:07,840
and we'll call this Challenge 2b, I'll call it compchallenge2b. I'm going to paste in the first part of the code, which

78
00:06:07,840 --> 00:06:13,930
we were aware of before, the locations and exits. Right so lets type in some code here now, so I'm going to type,

79
00:06:14,340 --> 00:06:17,620
so print parentheses nested for loops,

80
00:06:21,040 --> 00:06:23,780
print, let's just do a bit of a header there,

81
00:06:26,670 --> 00:06:40,080
for loc in sorted, parentheses locations colon, exits to destination underscore one, equals left and right square brackets.

82
00:06:40,960 --> 00:06:42,810
Then we want for exit,

83
00:06:42,810 --> 00:06:52,230
xit in exits colon, if loc in exits, left and right square brackets, and xit in those square brackets,

84
00:06:52,580 --> 00:06:58,200
dot values. You've seen a lot of this code before but it's helpful to type this in again, so we can see the list comprehension

85
00:06:58,200 --> 00:07:02,700
shortly, colon then exits

86
00:07:03,140 --> 00:07:10,930
underscore to underscore destination underscore one dot append, then two parentheses,

87
00:07:11,170 --> 00:07:18,270
xit comma space locations, left and right square brackets, xit within that, closing square bracket. Then

88
00:07:18,360 --> 00:07:26,310
we've got two right parentheses, and I've added three there to the append, that should only have been two. Lets fix that up, fixes

89
00:07:26,310 --> 00:07:35,400
that line up, and on the next line then, we go back to our for loop, to the same code level, and we'll print parentheses

90
00:07:35,420 --> 00:07:46,610
locations leading to, left and right curly braces, double quotes dot format, parentheses loc comma, then end

91
00:07:46,620 --> 00:07:55,800
equals, in single quotes a tab character, so that's backslash t parentheses. Then we'll do a print exits to destination

92
00:07:55,790 --> 00:07:56,400
underscore one.

93
00:07:59,530 --> 00:08:02,220
Right, then we'll just do an empty print there.

94
00:08:02,770 --> 00:08:04,690
Alright, so that's the nested for loop.

95
00:08:04,690 --> 00:08:08,690
Now let's look at creating the list comprehension inside a for loop.

96
00:08:08,970 --> 00:08:19,760
So we're going to do a print. print parentheses double quotes list comprehension inside a for loop,

97
00:08:26,080 --> 00:08:26,990
bit of a header there

98
00:08:31,060 --> 00:08:39,490
again, for loc in sorted locations colon, then exits to destination.

99
00:08:39,500 --> 00:08:47,840
This time it's going to be 2, equals left and right square brackets, parentheses xit comma locations, left and right

100
00:08:48,290 --> 00:08:55,810
square brackets, then xit, then our closing square bracket, closing parentheses, then for exit,

101
00:08:56,330 --> 00:08:57,610
xit in exits,

102
00:08:57,640 --> 00:09:06,530
e x i t s, if loc in exits, left and right square brackets, xit dot values parentheses.

103
00:09:06,650 --> 00:09:11,240
Then we've got our closing right square bracket, and then we just do print

104
00:09:14,200 --> 00:09:24,870
locations leading to left and right curly braces, double quotes dot format, then we've got loc comma, then the same end

105
00:09:24,870 --> 00:09:33,820
equals, single quotes and our tab character, backslash t again. Then we're just going to print out 'exits to destination

106
00:09:33,870 --> 00:09:40,090
2', and we'll just do an empty print on line 34.

107
00:09:40,090 --> 00:09:46,780
Right so that's two examples of producing lists of all the locations leading to each of the destinations.

108
00:09:46,790 --> 00:09:47,690
So if we run the program,

109
00:09:51,360 --> 00:09:56,110
I'll just make this a little bit bigger so we can see both examples there, and left to right you can see the output.

110
00:09:59,780 --> 00:10:04,440
So for each destination we get a list of the locations that lead directly to it.

111
00:10:04,510 --> 00:10:09,470
So we're getting six separate lists, which means we're going to need a listed list comprehension if you

112
00:10:09,470 --> 00:10:11,320
want to keep the same sort of structure.

113
00:10:11,830 --> 00:10:19,380
And obviously you can see here when we run this that we've got the same output for both methods.

114
00:10:19,470 --> 00:10:25,000
So again the first one was a nested for loop, the second was a list comprehension inside a for loop.

115
00:10:25,330 --> 00:10:29,280
And importantly remember that we need to put the outer loop at the end of the comprehension.

116
00:10:29,500 --> 00:10:31,310
So our nested comprehension then,

117
00:10:31,330 --> 00:10:34,900
let's just add that, it's going to be as follows:

118
00:10:34,900 --> 00:10:37,820
so I'm going to do that on line 36, we'll start,

119
00:10:38,740 --> 00:10:40,840
that's going to be print, lets do our nested,

120
00:10:47,620 --> 00:10:50,320
print, then a bit of a heading there.

121
00:10:57,390 --> 00:11:04,470
Alright, and so exits to destination 3 equals, lets add that.

122
00:11:04,510 --> 00:11:06,330
So we've done our two examples

123
00:11:06,430 --> 00:11:14,140
above. Lets do the third one, so it's going to be two square brackets, parentheses xit comma then locations,

124
00:11:14,720 --> 00:11:21,030
left and right square brackets, and xit within that, then closing parentheses, for xit in exits,

125
00:11:21,730 --> 00:11:22,610
in e x i t s that is.

126
00:11:22,630 --> 00:11:24,600
The second one,

127
00:11:25,120 --> 00:11:28,320
if loc in exits,

128
00:11:28,620 --> 00:11:35,440
so left and right square brackets, xit dot values parentheses,

129
00:11:35,520 --> 00:11:43,150
oops parentheses is already added, then for loc in sorted locations.

130
00:11:45,430 --> 00:11:50,210
Then we've got our closing parentheses and closing right bracket, and after the values it should've been a square

131
00:11:50,210 --> 00:11:51,030
bracket as well.

132
00:11:51,110 --> 00:12:03,430
Put square bracket, then let's print exits to destination underscore 3, and lets just make that so it fits better.

133
00:12:03,600 --> 00:12:05,480
I'm going to put that here, put the line break so that it goes

134
00:12:05,540 --> 00:12:08,910
to the next line. That's a little bit nicer to see now.

135
00:12:09,320 --> 00:12:16,940
So basically the output when we run it, contains each of the six lists of the previous two code snippets

136
00:12:16,940 --> 00:12:17,930
created.

137
00:12:18,080 --> 00:12:23,200
Now being a nested list, a list containing other lists is not formatting as nicely.

138
00:12:23,360 --> 00:12:31,940
So we can see the six locations, from 0 to 5 in the first list. I'll just move that over, 2, 3, 4, 5, but

139
00:12:31,940 --> 00:12:33,450
then a new list starts, and

140
00:12:33,490 --> 00:12:40,310
you see that it contains location 3, 4 and then 5 and so on, and it goes on to another one.

141
00:12:40,310 --> 00:12:47,910
Basically the one after that is 1, 4 and 5 and the next 2, just scrolling over, only contained location 1 because

142
00:12:47,910 --> 00:12:56,130
the last list has locations 1 and 2, and everything agrees with the output produced using the previous two methods.

143
00:12:56,140 --> 00:13:00,810
Now that said, if you wanted to print it out as prettily as the first two bis of code,

144
00:13:00,910 --> 00:13:07,370
what we can do is use the enumerate function to get the index of each list in the other list.

145
00:13:07,480 --> 00:13:08,790
So lets go about doing that.

146
00:13:11,740 --> 00:13:13,970
So we'll have a print there,

147
00:13:14,980 --> 00:13:21,010
then for index comma space loc in enumerate

148
00:13:21,510 --> 00:13:31,450
then it's going to be parentheses exits to destination 3 colon, and we'll do a print, parentheses locations leading

149
00:13:31,450 --> 00:13:41,500
to, left and right curly braces, dot format parentheses and index within that, comma, and end equals, in single

150
00:13:41,500 --> 00:13:43,970
quotes our tab character, backslash t,

151
00:13:44,370 --> 00:13:52,130
then you could print loc. So we can run that, and you can see we've now got our output

152
00:13:55,100 --> 00:14:00,400
in the correct format. So Python contains a load of useful functions such as

153
00:14:00,410 --> 00:14:05,390
enumerate, and if you weren't aware that it existed you might mess around incrementing an index variable

154
00:14:05,630 --> 00:14:06,830
inside the for loop,

155
00:14:07,040 --> 00:14:09,890
but enumerate takes care of all of that for us.

156
00:14:09,970 --> 00:14:15,230
And if you haven't already, I'd suggest it's worth spending time to become familiar with the builtin functions,

157
00:14:15,780 --> 00:14:19,540
and you can find the documentation list, or find the documentation I should say,

158
00:14:22,510 --> 00:14:26,880
here, and I'll put a link in the resources section of the video.

159
00:14:26,990 --> 00:14:28,670
That's a good place to start.

160
00:14:28,790 --> 00:14:31,940
Now, I'm not suggesting you memorise all these functions.

161
00:14:32,030 --> 00:14:37,160
Just be aware that they exist so that you can refer back here when you need to know how to use them.

162
00:14:37,160 --> 00:14:41,690
There's a lot of very useful functions in the standard library, and we're going to be looking at a few

163
00:14:41,690 --> 00:14:44,720
that are related to comprehensions after the next video.

164
00:14:44,990 --> 00:14:48,890
But for now I'm going to stop this video because it's got quite long, and in the next one we're going

165
00:14:48,890 --> 00:14:54,080
to look at that timeit module that I mentioned previously, to see how these various approaches compare

166
00:14:54,410 --> 00:14:56,230
in terms of performance.

167
00:14:56,240 --> 00:14:57,670
So see you in the next video.

