Bummer! This is just a preview. You need to be signed in with a Pro account to view the entire video.
Start a free Basic trial
to watch this video
Quite often we have an iterable that has an answer in it. How do we get that answer out, though? Let's look at `reduce()` and the concept of recursion.
functools.reduce()
takes a function and an iterable. The function, though, takes two arguments. The first time it runs, the two arguments will be the first two items in the iterable. Every time after that, the first argument will be the result of the last time the function was run. The second argument will be the next value from the iterable. When the iterable is out of items, reduce()
will return whatever the function returned last.
Think about adding up all of the numbers in a column. You add the top two, then add the third number to the sum you got from the first two. Then you add the fourth number to the sum of the top three, and so on.
Calling a function over again from within itself is known as recursion and it's what makes reduce()
able to do its job.

0:00
[MUSIC]

0:04
When you learn about functional programming,

0:07
you generally learn about three tools, map, filter, and our next one, reduce.

0:11
Often you'll even here map and reduce used together, but we'll get to that later.

0:16
First though, let's talk about reduce on its own and a concept we've used but

0:20
never really focused on.

0:22
Reduce takes a function and an iterable,

0:24
and then applies the function to the first two items in the iterable.

0:28
Then it takes the return value of that function and applies the function again

0:32
with that originally returned value and the next item in the iterable.

0:36
Eventually, of course, the iterable runs out of values, and

0:39
reduce returns the last value that came out of the function.

0:42
When we talk about a function that repeatedly calls itself to get new values

0:45
we say that the function is recursive.

0:48
We've written a few recursive functions in the past.

0:50
It's a very useful technique.

0:52
Okay let's go see how to use reduce.

0:55
So reduce let's get an answer from an iterable.

1:00
So we can be like, hey what's the sum of all these things?

1:03
Although then we can use sum.

1:04
[LAUGH] Or we can do what's all these things multiplied together?

1:07
Or whatever.

1:09
So let's do a simple function to play with reduce, and

1:13
then we'll do something a little bit more complicated.

1:15
So let's just do def product, and it's gonna take two variables, x and y, and

1:20
it's gonna return x times y.

1:23
So it's gonna multiply these things together.

1:25
Now to use reduce, we need to import it.

1:28
So we're gonna come up here, I'm going to say from functools import reduce.

1:35
So now we're gonna print(reduce(product, and then let's do [1, 2, 3, 4, 5].

1:45
All right, so we want to print the product of our five numbers there.

1:50
So do python stock.py and we get 120.

1:55
The first time product runs through it goes hey, do I have an x and a y?

2:00
No I don't, okay.

2:01
So let's take the first item for x and the second item for y.

2:05
So we take 1 and 2 and multiply those together and we get 2.

2:08
So then product goes okay cool, I've got 2 as my answer of the last time.

2:13
I'm gonna make that x.

2:14
And then I'm gonna get the next item as y.

2:17
So that's 3, so 2 times 3, well that's 6.

2:20
Okay, so let's run again.

2:22
Is there more stuff in the interval?

2:23
There is, let's run again.

2:24
So now six is our x and then we do six times four, you get the idea?

2:29
Keep moving along.

2:30
Alright.

2:31
So, that's what reduce does.

2:33
Now, reduce is kinda like a for loop that has an outside value.

2:38
If we had total = 0 and then we do for

2:44
x in [1, 2, 3, 4, 5].

2:51
Total = total x x.

2:56
And then we were to print(total), we should get 120 again.

3:04
Oh of course, that's because total = 0.

3:08
If total else, no so let's do x.

3:16
We gotta get tricky here.

3:18
x x total if total else x x 1.

3:26
There we go.

3:27
So we don't wanna multiply against zero, right?

3:29
So I really we guess don't stop at one and then just do the x x total.

3:36
[NOISE], same answer.

3:37
But that's messy.

3:39
We don't wanna do code like that if we can help it.

3:41
That's just ridiculous.

3:43
I mean, there's cases for it, but reduce makes this a lot nicer.

3:47
So let's do one that's actually working with our books.

3:50
Let's do a new def let's do add_book_prices.

3:53
This is a little bit different

3:57
because we have to get the price attribute off of the book, right?

4:02
So we have to deal with numbers.

4:04
So we're gonna return book1 + book2.

4:09
And we're gonna make it so that we're not fetching the numbers off of there.

4:11
So we're gonna do total = reduce(add_book_prices,.

4:17
And then we're gonna use a list comprehension.

4:20
We're gonna say, [b.price for b in BOOKS]).

4:27
And then let's print(total), all right?

4:30
So that's gonna give us a good sized number, $225.30.

4:35
We could also do this with just a random number of books if we wanted.

4:39
If we wanted to bring in the random library and play with that kinda stuff.

4:42
But you get the idea.

4:44
We're adding up all of those.

4:47
We could also do we've got ten books, or whatever,

4:50
and we wanna add all those together.

4:54
But I wanna talk first about what this is really doing.

4:57
So it's kind of deceptive.

5:00
It looks really simple.

5:02
But let's do this.

5:03
Let's look at def long_total and we're gonna say (a = None,

5:07
b = None, books = None):.

5:11
And if a is None and b is None and books is None,

5:15
then we're gonna return None, cuz we've got nothing out.

5:18
Right? So if a is None and b is None and

5:22
books is not None, then a = books.pop(0),

5:28
b = equal books.pop(0).

5:31
So take the first two items off the thing, and

5:35
then we’re gonna return long_total(a, b, books).

5:40
Now, of course, we could've done the pops inside the return long total, but

5:43
we're not.

5:45
If a is not None and books, so books exists.

5:50
And books is not None and b is None.

5:54
So, we have an a, we have books, and books isn't None, just to make sure.

6:01
Then b = books.pop(0).

6:05
Return long_total(a, b, books).

6:10
And if a is not None and

6:14
b is not None and books is not None.

6:19
Then we're gonna return long_total(a + b, None, books).

6:26
Because we wanna add together a and b, the two things that got passed in, and then we

6:31
want to put another None in there so that we take the next item off the list, right?

6:35
And we actually wanna do this one again.

6:42
Let's say and not books.

6:46
So if we have an a and we have a a, but we don't have any books,

6:49
the books is now empty.

6:50
Then we wanna return None for all of those.

6:56
And then finally if a is not None and b is None and not books or books is None.

7:03
We wanna just return a.

7:07
So we did all that work.

7:08
What did all that work do for us?

7:10
Well, let's print long_total(None,

7:16
None, [b.price for

7:20
b in BOOKS])) And

7:27
if we run this, oops.

7:33
Is not None.

7:38
There's our total again, $225.

7:40
So what this long total is doing

7:44
is basically the same as what these two lines did.

7:50
So we kinda have to think about how far do we wanna go through this, right?

7:55
And what it's doing is you notice in here we keep returning long total, right?

7:59
We return long total until there's no more stuff to keep returning

8:03
inside of long total.

8:04
And that's called recursion, when we keep reusing that same function.

8:08
So let's do one more little thing about recursion.

8:12
So we'll do factorial.

8:14
So factorial is the product of a number and all the numbers less than a certain

8:20
number, so if n=1, so if n is 1, return 1.

8:25
Because 1 times 1 times 1 is [NOISE] always one.

8:28
Otherwise return n x factorial(n1).

8:34
[NOISE] So if we print(factorial(5)).

8:40
Then we get 5 times 4 times 3 times 2 times 1.

8:43
We get 120.

8:45
So this is another recursive one.

8:47
We keep returning another call to the same function.

8:49
We keep building up a stack.

8:52
So it's a really handy thing to know about, it's a handy thing to know exists,

8:56
and it's a handy thing to know that that's what reduce is doing.

9:00
It's using recursive functions to calculate a final total.

9:04
Reduce is a great way to get answers out of an interval.

9:08
You can combine it with map, filter, or both

9:10
to get an answer about just a subset of an interval, or an altered version of it.

9:15
So far we've been writing full functions for all of our filter, map, and

9:18
reduce work, but we don't have to.

9:21
Python, like JavaScript and many other languages, has a concept known as

9:24
anonymous functions, and we can use these for our needs.

9:28
Let's learn about them in the next video.
You need to sign up for Treehouse in order to download course files.
Sign up