1
00:00:04,530 --> 00:00:07,109
So now that we've seen Map and Filter,

2
00:00:07,109 --> 00:00:08,850
it should hopefully be easier to understand

3
00:00:08,850 --> 00:00:11,370
how Reduce works. I covered those two

4
00:00:11,370 --> 00:00:13,860
functions first because Reduce takes the

5
00:00:13,860 --> 00:00:15,870
same arguments and we now understand

6
00:00:15,870 --> 00:00:18,450
what they are. What reduce does though,

7
00:00:18,450 --> 00:00:20,910
is a bit harder to understand. It takes a

8
00:00:20,910 --> 00:00:23,640
function and a sequence, then reduces the

9
00:00:23,640 --> 00:00:26,490
sequence to a single value by repeatedly

10
00:00:26,490 --> 00:00:28,949
calling the function. The documentation

11
00:00:28,949 --> 00:00:30,060
is a really good example of

12
00:00:30,060 --> 00:00:32,009
documentation that's only useful

13
00:00:32,009 --> 00:00:34,710
after you already understand it. So we're going

14
00:00:34,710 --> 00:00:41,190
to just check that out briefly now. So

15
00:00:41,190 --> 00:00:42,690
the first thing to note there, in that

16
00:00:42,690 --> 00:00:44,820
link, is that Guido didn't remove it

17
00:00:44,820 --> 00:00:47,340
from Python, obviously, but he did get it

18
00:00:47,340 --> 00:00:49,379
removed to the functools module.

19
00:00:49,379 --> 00:00:51,809
You can see there, functools, and if we scroll

20
00:00:51,809 --> 00:00:53,129
down we can see here the functools

21
00:00:53,129 --> 00:00:55,559
dot reduce function. So he managed

22
00:00:55,559 --> 00:00:57,120
to get it moved into the functools module.

23
00:00:57,120 --> 00:00:59,219
So basically, Reduce is no longer

24
00:00:59,219 --> 00:01:01,680
a built-in function in Python 3. You have

25
00:01:01,680 --> 00:01:04,559
to import functools if you want to

26
00:01:04,559 --> 00:01:06,390
use it. Alright, so let's have a look at an

27
00:01:06,390 --> 00:01:08,070
example. We're going to start with the

28
00:01:08,070 --> 00:01:09,990
example in the documentation because

29
00:01:09,990 --> 00:01:12,630
it's quite simple. It uses a Lambda which

30
00:01:12,630 --> 00:01:14,130
we haven't covered yet, so I'm going to

31
00:01:14,130 --> 00:01:15,960
rewrite it using an ordinary

32
00:01:15,960 --> 00:01:19,049
function. I'll go back to IntelliJ, create a new

33
00:01:19,049 --> 00:01:21,720
file. This time, this new Python file,

34
00:01:21,720 --> 00:01:27,270
we'll call this reduceintro.py. Now let's

35
00:01:27,270 --> 00:01:28,409
add the code, so we'll start by

36
00:01:28,409 --> 00:01:33,090
typing import timeit and import func

37
00:01:33,090 --> 00:01:37,979
tools, and our first function on line 5,

38
00:01:37,979 --> 00:01:40,250
def calc underscore values

39
00:01:40,250 --> 00:01:44,270
parenthesis x comma space y colon int,

40
00:01:44,270 --> 00:01:46,560
then the closing right parenthesis and a

41
00:01:46,560 --> 00:01:49,020
colon. Then the value we want to return

42
00:01:49,020 --> 00:01:54,600
is x plus y. Okay and then on line 9 I'm

43
00:01:54,600 --> 00:01:57,840
going to type numbers equals left square

44
00:01:57,840 --> 00:02:04,229
bracket 2, 3, 5, 8, 13 and then on line 11,

45
00:02:04,229 --> 00:02:07,979
reduced underscore value equals and

46
00:02:07,979 --> 00:02:09,329
we're going to call our Reduce function.

47
00:02:09,329 --> 00:02:10,199
So it's going to be func

48
00:02:10,199 --> 00:02:15,330
tools dot reduce parentheses it's going to be

49
00:02:15,330 --> 00:02:19,450
calc underscore values comma space numbers

50
00:02:19,450 --> 00:02:22,100
and let's print that value out, print reduce

51
00:02:22,100 --> 00:02:24,709
underscore value. That should be calc

52
00:02:24,709 --> 00:02:26,840
underscore values, being the name of the

53
00:02:26,840 --> 00:02:32,770
function. Alright, run the program

54
00:02:32,770 --> 00:02:34,819
now we see that we've got the sum

55
00:02:34,819 --> 00:02:36,950
of all the numbers in the list, which is 31;

56
00:02:36,950 --> 00:02:41,209
2 plus 3 is 5, 5 is 10, 8 is 18 plus 13

57
00:02:41,209 --> 00:02:43,970
is 31, being the list on line 9. So we've

58
00:02:43,970 --> 00:02:46,790
got the sum of that list which is 31.

59
00:02:46,790 --> 00:02:48,050
Now I'll go through exactly what it's

60
00:02:48,050 --> 00:02:50,209
doing at the moment. Before that though,

61
00:02:50,209 --> 00:02:51,170
I want to refer back to

62
00:02:51,170 --> 00:02:53,510
Guido's comments that we saw earlier.

63
00:02:53,510 --> 00:02:55,070
So let's just go back and open it up again

64
00:02:55,070 --> 00:03:02,030
in a browser. You can see there's a few

65
00:03:02,030 --> 00:03:04,040
paragraphs down here. He's talking

66
00:03:04,040 --> 00:03:06,050
about the fact that Reduce - this is actually

67
00:03:06,050 --> 00:03:08,660
the one I've always hated most. Unless

68
00:03:08,660 --> 00:03:11,540
the function's trivial, as ours is, even Guido

69
00:03:11,540 --> 00:03:13,550
van Rossum struggles to understand

70
00:03:13,550 --> 00:03:15,739
what's going on. As he says, we already

71
00:03:15,739 --> 00:03:18,410
have a sum function to take care

72
00:03:18,410 --> 00:03:20,630
of addition. So back in our code, we can write

73
00:03:20,630 --> 00:03:24,220
what we've done there, quite simply, with

74
00:03:24,220 --> 00:03:27,890
print parentheses sum parentheses

75
00:03:27,890 --> 00:03:33,950
numbers. Click and run that, and obviously, we

76
00:03:33,950 --> 00:03:36,049
get the same result. So getting back

77
00:03:36,049 --> 00:03:39,049
to Guido's blog post, he talked about using

78
00:03:39,049 --> 00:03:41,540
product to calculate the product of a

79
00:03:41,540 --> 00:03:43,820
sequence - that didn't get added to Python.

80
00:03:43,820 --> 00:03:46,489
There is a product function in the

81
00:03:46,489 --> 00:03:49,220
itertools module, but that

82
00:03:49,220 --> 00:03:50,870
does something different. It calculates

83
00:03:50,870 --> 00:03:52,850
the Cartesian product which is useful

84
00:03:52,850 --> 00:03:55,850
when dealing with sets, for example. Guido

85
00:03:55,850 --> 00:03:57,859
proposed adding all and any to the

86
00:03:57,859 --> 00:03:59,750
built-in functions. That's been done and

87
00:03:59,750 --> 00:04:01,280
we'll look at those in a minute.

88
00:04:01,280 --> 00:04:03,200
The upshot of this discussion

89
00:04:03,200 --> 00:04:05,630
is that there's very rarely any need to use

90
00:04:05,630 --> 00:04:08,299
Reduce in your code. However, many people

91
00:04:08,299 --> 00:04:10,190
disagreed and there's a link to the

92
00:04:10,190 --> 00:04:11,630
comments at the bottom of the post,

93
00:04:11,630 --> 00:04:13,239
if you go down and have a look -

94
00:04:13,239 --> 00:04:15,799
118 comments there - so you can go ahead

95
00:04:15,799 --> 00:04:17,298
and check those and see why people have

96
00:04:17,298 --> 00:04:18,978
disagreed with it, if you want. Now going

97
00:04:18,978 --> 00:04:21,858
back to our code now, let's see how

98
00:04:21,858 --> 00:04:23,450
Reduce works so that you understand

99
00:04:23,450 --> 00:04:25,039
what's happening. You'll need to know

100
00:04:25,039 --> 00:04:26,990
what it's doing if you come across it in

101
00:04:26,990 --> 00:04:29,090
code that you have to maintain. Alright,

102
00:04:29,090 --> 00:04:31,190
so looking at our list on line 9, we've

103
00:04:31,190 --> 00:04:32,330
got five numbers.

104
00:04:32,330 --> 00:04:35,030
What reduce is doing, is calling our

105
00:04:35,030 --> 00:04:37,370
calc underscore values function with the

106
00:04:37,370 --> 00:04:39,440
first two items in the list, 2 and

107
00:04:39,440 --> 00:04:42,500
3, then returns the result 5.

108
00:04:42,500 --> 00:04:45,050
It uses that value and the next item in the

109
00:04:45,050 --> 00:04:47,090
list when it calls calc underscore

110
00:04:47,090 --> 00:04:49,909
values again. So that returns 10, so

111
00:04:49,909 --> 00:04:52,610
10 becomes the first argument in the next

112
00:04:52,610 --> 00:04:55,069
call, to the next call, of calc underscore

113
00:04:55,069 --> 00:04:57,139
values. So if you wanted to know what a

114
00:04:57,139 --> 00:04:58,669
long hand, or say a long-handed

115
00:04:58,669 --> 00:05:00,289
version of what's happening here,

116
00:05:00,289 --> 00:05:01,460
we could type that out. It'll be something

117
00:05:01,460 --> 00:05:05,900
along these lines; it'll be result equals

118
00:05:05,900 --> 00:05:10,240
calc underscore values 2 comma 3

119
00:05:10,240 --> 00:05:14,409
and let's just, actually, I'll do the next one, result

120
00:05:14,409 --> 00:05:16,729
equals and it's calc values again. This

121
00:05:16,729 --> 00:05:19,639
time it's result comma 5 and now

122
00:05:19,639 --> 00:05:21,349
I'll copy the lines, I'll copy the next two

123
00:05:21,349 --> 00:05:24,020
lines, and so it's result comma 5

124
00:05:24,020 --> 00:05:26,810
result comma 8 this time, then result

125
00:05:26,810 --> 00:05:31,719
comma 13, and then we can print result.

126
00:05:31,719 --> 00:05:35,180
We can run that, and you can see we've

127
00:05:35,180 --> 00:05:37,520
got the same value there. So each time

128
00:05:37,520 --> 00:05:39,800
around, the function is called with the

129
00:05:39,800 --> 00:05:41,960
result from the previous call and the

130
00:05:41,960 --> 00:05:44,270
next item in the list, and you can see

131
00:05:44,270 --> 00:05:45,979
that when I ran the program, we got 31

132
00:05:45,979 --> 00:05:48,199
returned for a third time. Alright so

133
00:05:48,199 --> 00:05:50,180
addition's easy but the sum function is a

134
00:05:50,180 --> 00:05:52,240
much easier way to do the same thing.

135
00:05:52,240 --> 00:05:54,800
Multiplication is also trivial, so if I

136
00:05:54,800 --> 00:05:56,389
go ahead and change our calc underscore

137
00:05:56,389 --> 00:05:58,789
values function to perform multiplication

138
00:05:58,789 --> 00:06:00,680
instead, by changing the plus to a

139
00:06:00,680 --> 00:06:03,889
multiplication, which is the star.

140
00:06:03,889 --> 00:06:06,889
of course. If I run that again now,

141
00:06:06,889 --> 00:06:10,069
this time we get the value 3120. The sum

142
00:06:10,069 --> 00:06:11,479
is still 31, of course, and there's no

143
00:06:11,479 --> 00:06:12,830
built-in function to calculate

144
00:06:12,830 --> 00:06:15,289
the product of a list. If you wanted to

145
00:06:15,289 --> 00:06:17,210
calculate the product without using

146
00:06:17,210 --> 00:06:19,909
Reduce, then you'd have to use a loop.

147
00:06:19,909 --> 00:06:22,099
So what I can do is comment out the call,

148
00:06:22,099 --> 00:06:26,479
the call to sum there - comment that out. So

149
00:06:26,479 --> 00:06:32,319
result equals 1 for x in numbers colon

150
00:06:32,319 --> 00:06:38,599
result star equals x and then we can

151
00:06:38,599 --> 00:06:40,780
print result.

152
00:06:40,780 --> 00:06:43,600
We could run that, and then we get the

153
00:06:43,600 --> 00:06:46,750
value of 3120 again. Basically, all

154
00:06:46,750 --> 00:06:50,110
three methods are giving the same answer. We've

155
00:06:50,110 --> 00:06:51,610
been discussing comprehensions in this

156
00:06:51,610 --> 00:06:52,930
section and I mentioned that every

157
00:06:52,930 --> 00:06:55,450
comprehension can be re-written as a

158
00:06:55,450 --> 00:06:58,780
loop. The opposite though, isn't true.

159
00:06:58,780 --> 00:06:59,860
You may be expecting me to write

160
00:06:59,860 --> 00:07:01,540
a comprehension that does the same thing

161
00:07:01,540 --> 00:07:03,580
as Reduce - we did that with Map and

162
00:07:03,580 --> 00:07:05,980
Filter after all - but you can't

163
00:07:05,980 --> 00:07:08,950
replace Reduce with a comprehension. Well that's

164
00:07:08,950 --> 00:07:10,900
not strictly true - you can pretty much do

165
00:07:10,900 --> 00:07:12,940
anything you want with enough code.

166
00:07:12,940 --> 00:07:15,100
If you search for solutions online, you'll

167
00:07:15,100 --> 00:07:17,110
find some. You'll also see their authors

168
00:07:17,110 --> 00:07:18,940
describing the solutions as insane,

169
00:07:18,940 --> 00:07:21,490
and not in a good way. You should now be

170
00:07:21,490 --> 00:07:23,170
able to work out what reduce is doing

171
00:07:23,170 --> 00:07:24,940
though, if you come across it in code

172
00:07:24,940 --> 00:07:26,860
that you have to use or maintain,

173
00:07:26,860 --> 00:07:28,870
and we'll leave it up to you to decide

174
00:07:28,870 --> 00:07:31,090
whether to use it in your own code. So

175
00:07:31,090 --> 00:07:33,010
let's finish this video here, and in the

176
00:07:33,010 --> 00:07:33,610
next one,

177
00:07:33,610 --> 00:07:36,070
we'll take a look at All and Any. See you

178
00:07:36,070 --> 00:07:38,790
in the next video.

