WEBVTT

0
00:00.180 --> 00:01.410
In the last lesson,

1
00:01.470 --> 00:06.120
we had a primer on functions so that we can understand the next step

2
00:06.150 --> 00:07.920
which is the Python decorator.

3
00:08.430 --> 00:11.700
So we've seen that functions can have functionality, inputs,

4
00:11.700 --> 00:16.700
and outputs, functions are first-class objects and can be passed around as arguments,

5
00:17.280 --> 00:19.650
functions can be nested in other functions,

6
00:19.920 --> 00:24.900
and finally, functions can be returned as the output from another function

7
00:25.200 --> 00:29.700
without needing to trigger it. With these four things in mind,

8
00:29.790 --> 00:33.180
we're finally ready to tackle the Python decorator.

9
00:34.200 --> 00:34.950
First of all,

10
00:34.950 --> 00:39.950
I'm actually going to create a Python decorator for you so that we can talk

11
00:40.140 --> 00:41.460
about how it works.

12
00:42.060 --> 00:45.300
Here's what a Python decorator function looks like.

13
00:45.780 --> 00:49.590
We started off by creating just a normal function.

14
00:50.910 --> 00:53.580
Let's say I call it my decorator_function.

15
00:56.190 --> 01:00.000
This function is going to take another function as an input.

16
01:00.960 --> 01:05.760
Now, inside the decorator_functionn, I'm going to nest a wrapper_function.

17
01:07.530 --> 01:12.530
And this wrapper_function is then going to trigger the actual function that was

18
01:13.770 --> 01:16.440
passed in to the decorator function.

19
01:17.760 --> 01:22.020
And at the end of calling all the lines in my decorator_function,

20
01:22.290 --> 01:26.490
I'm going to return my wrapper_function. But remember

21
01:26.520 --> 01:30.090
without the parentheses. Now,

22
01:30.120 --> 01:33.750
basically what we've done is we've created a decorator_function

23
01:33.840 --> 01:38.840
which can do some stuff and it could control the calling

24
01:39.270 --> 01:40.860
of the function that was passed in.

25
01:41.550 --> 01:46.550
Remember that a decorator_function is just a function that wraps another

26
01:46.890 --> 01:51.390
function and gives that function some additional functionality.

27
01:51.810 --> 01:56.550
That's quite a mouthful, but let's take a look at an example.

28
01:57.390 --> 02:00.630
Let's say that I wanted to create a simple function

29
02:00.720 --> 02:02.880
which I'll call say_hello.

30
02:03.510 --> 02:06.360
Now this function is going to be the simplest form of function.

31
02:06.390 --> 02:09.000
It has no inputs and it has no outputs

32
02:09.270 --> 02:13.620
and all it does is just going to print hello. Now,

33
02:13.620 --> 02:17.280
what if I don't want to run this immediately

34
02:17.310 --> 02:21.630
the moment when I hit run, what if I wanted to add a delay to this function?

35
02:22.170 --> 02:25.980
Well, one way of doing that would be importing the time module

36
02:26.460 --> 02:28.680
and then before we print hello,

37
02:29.010 --> 02:32.520
we can go ahead and run time.sleep

38
02:32.850 --> 02:36.660
and we can sleep for a prespecified number of seconds.

39
02:37.290 --> 02:40.950
So now when I call this method, say_hello,

40
02:41.370 --> 02:45.420
and when I run it, you'll see that immediately nothing happens.

41
02:45.720 --> 02:49.440
And then after a two second delay, you can see the print

42
02:49.470 --> 02:52.290
hello actually gets triggered. Now,

43
02:52.290 --> 02:55.320
what if I wanted to create a whole bunch of functions

44
02:55.380 --> 02:58.080
like say_bye and say_greeting.

45
02:59.830 --> 03:04.510
And I wanted to add a delay onto each of these. Well,

46
03:04.510 --> 03:09.130
then I would have to copy and paste this code into all three places.

47
03:09.790 --> 03:12.010
Now, this is a very simple example,

48
03:12.280 --> 03:17.280
but frequently we'll want to add some additional piece of functionality to a

49
03:17.380 --> 03:22.270
number of our functions. So this is where the decorator comes in handy.

50
03:23.140 --> 03:27.850
What we could do is before we trigger the function that's passed in to

51
03:27.850 --> 03:31.420
the decorator_function, we can add the delay.

52
03:31.960 --> 03:36.960
So now whenever we decorate a function with this particular decorator_function,

53
03:38.590 --> 03:43.030
then it's going to delay for two seconds before it runs the function.

54
03:43.600 --> 03:48.010
So let's give this decorator function a little bit more of a descriptive name.

55
03:48.220 --> 03:51.940
Let's call it a delay_decorator. Well,

56
03:51.970 --> 03:56.970
now what we can do is we can simply use an @ sign

57
03:58.660 --> 04:03.660
and we can call the delay_decorator in front of the methods

58
04:05.320 --> 04:09.730
which we want to delay. So we can add it to all three of them,

59
04:09.760 --> 04:12.040
or we can only add it to some of them.

60
04:12.400 --> 04:17.050
But now when I actually run my function, say_hello

61
04:17.050 --> 04:20.650
for example, you can see that this one

62
04:20.650 --> 04:22.630
because it's got the delay decorator

63
04:22.900 --> 04:26.260
it's going to wait for two seconds before it prints hello.

64
04:26.650 --> 04:28.930
But if I call say_greeting

65
04:29.050 --> 04:31.900
which is the one that doesn't have the decorator above it,

66
04:32.260 --> 04:34.660
then you can see it gets triggered immediately.

67
04:35.350 --> 04:40.350
So this is a really nice way of adding something that you could do before you

68
04:40.600 --> 04:41.560
run the function,

69
04:42.360 --> 04:43.193
<v 1>Right?</v>

70
04:45.630 --> 04:50.630
<v 0>or adding some functionality which you can do after the function. Or</v>

71
04:51.510 --> 04:56.340
alternatively, you can modify the function so maybe you wanna run it twice.

72
04:56.910 --> 04:59.070
So now when I say hello,

73
05:01.950 --> 05:04.530
it's going to not only delay by two seconds,

74
05:04.800 --> 05:06.750
but it's also going to run it twice.

75
05:09.270 --> 05:14.220
This syntax is what we saw when we were creating our Flask

76
05:14.250 --> 05:19.250
app. It's got the @ sign and it basically decorates the function below with a

77
05:20.850 --> 05:22.050
decorator function.

78
05:22.080 --> 05:27.080
So putting this function through a machine that could modify the function or add

79
05:28.200 --> 05:32.400
some functionality before or after. Coming back to our definition,

80
05:32.820 --> 05:37.820
a decorator function is simply a function which wraps another function and gives

81
05:40.500 --> 05:44.640
it some additional functionality or modifies the functionality.

82
05:46.500 --> 05:51.390
Now, coming back to this syntax, this @ sign, it's

83
05:51.390 --> 05:54.150
what's known as syntactic sugar.

84
05:54.930 --> 05:59.930
It's some syntax that you can write to make it easier to write an alternative

85
06:01.430 --> 06:02.263
line of code.

86
06:02.810 --> 06:07.760
So let's say we wanted to add the decorator to this say_greeting. Well,

87
06:07.910 --> 06:11.450
if instead of using this syntactic sugar with the @ sign

88
06:11.450 --> 06:12.920
and then the name of the function,

89
06:13.280 --> 06:18.280
we could also just call the name of the decorator and then we could pass in the

90
06:20.570 --> 06:23.510
name of our function, say_greeting,

91
06:24.620 --> 06:29.620
and then we would end up with the decorated function as the output from this

92
06:31.310 --> 06:32.143
method.

93
06:32.660 --> 06:37.660
And we can now call the decorated function with the parentheses.

94
06:38.570 --> 06:43.310
So now we've triggered this say_greeting function

95
06:43.400 --> 06:45.860
and we've passed it through the delay decorator.

96
06:46.520 --> 06:51.520
But it's much easier to see at a glance what's going on by using this @ sign

97
06:51.980 --> 06:56.270
because you can see now you can just trigger this method by its own name

98
06:56.630 --> 07:00.020
and because the @delay_decorator is on top of it,

99
07:00.260 --> 07:02.540
then it's going to go through that filter.

100
07:03.950 --> 07:07.250
I recommend spending a few minutes looking at this code

101
07:07.520 --> 07:11.180
which you can access at this URL which is in the course resources,

102
07:11.660 --> 07:16.370
and then trying to recreate this functionality from scratch based on your

103
07:16.370 --> 07:20.360
understanding of what we just talked about. And then once you're done,

104
07:20.420 --> 07:23.510
when we head back to our Flask application

105
07:23.870 --> 07:27.890
you can now see that pretty much all of the code is easily understood.

106
07:28.340 --> 07:31.580
We know what this __name__ refers to,,

107
07:31.910 --> 07:34.160
we know that this is a decorator

108
07:34.400 --> 07:38.270
which is going to make sure that we only trigger this function

109
07:38.570 --> 07:41.840
if the user's trying to access the URL

110
07:42.020 --> 07:45.010
that is the homepage/.

111
07:46.160 --> 07:50.540
If we wanted to create another function, let's call it say_bye.

112
07:53.480 --> 07:56.840
This function could also get a decorator

113
07:57.350 --> 08:01.970
and this decorator will check to see well, if somebody goes to the URL 

114
08:01.970 --> 08:03.260
/bye, well

115
08:03.260 --> 08:07.160
then we're going to be triggering this method. Effectively

116
08:07.610 --> 08:12.610
the Flask framework is the one that determines which of these methods to call

117
08:14.180 --> 08:19.180
and these methods are only called when the decorator says that it's appropriate to do

118
08:19.820 --> 08:24.080
so. Now, if I go ahead and run this code once more,

119
08:26.390 --> 08:29.390
and we go to the URL that is our server,

120
08:29.720 --> 08:33.650
so this we know is the home route or the homepage,

121
08:33.980 --> 08:36.560
but if we go to /bye

122
08:36.920 --> 08:41.920
then we go to the bye route and this method gets rendered.

123
08:43.730 --> 08:47.330
Now in order to make sure that you get a chance writing decorator functions

124
08:47.330 --> 08:50.090
yourself, if you head over to the next lesson,

125
08:50.120 --> 08:53.720
I've got a coding exercise for you to challenge you

126
08:53.750 --> 08:55.760
to create your own decorator functions.

127
08:56.270 --> 08:59.540
And it's going to be a really useful decorator function because it's going to

128
08:59.540 --> 09:03.290
measure the amount of time that it takes a particular function to run.

129
09:03.920 --> 09:06.830
So for all of that and more, I'll see you on the next lesson.