WEBVTT

0
00:00.510 --> 00:05.510
The next part of the syntax that might be unfamiliar is this @ sign and

1
00:07.050 --> 00:11.460
something that comes after the @ sign. Now we sort of know what it does.

2
00:11.460 --> 00:14.790
It's basically saying when the user hits up this path

3
00:14.820 --> 00:19.170
which is what's called the home route, basically when you go to a website,

4
00:19.200 --> 00:21.540
for example, www.google.com

5
00:21.870 --> 00:26.610
and you go to the first forward slash well, that is going to be the home.

6
00:27.180 --> 00:31.080
And it knows that when you go there you want to see the home page.

7
00:31.530 --> 00:33.480
So that's effectively what we're saying here.

8
00:33.690 --> 00:38.670
When the user navigates to our URL with just a forward slash they want to see

9
00:38.670 --> 00:41.580
the homepage and so we're going to show them hello world.

10
00:42.210 --> 00:46.320
But what is this syntax exactly? Well,

11
00:46.320 --> 00:49.230
this is code a Python decorator

12
00:49.800 --> 00:54.210
and this is something that you'll see in more advanced Python projects.

13
00:54.540 --> 00:57.420
So what exactly is a decorator? Well,

14
00:57.450 --> 01:01.320
let's imagine that you have a bunch of functions in your class or in your

15
01:01.320 --> 01:02.153
module

16
01:02.460 --> 01:07.460
and you want to add some functionality to each of these functions. Well then you

17
01:09.780 --> 01:12.990
might use a decorator function to do that.

18
01:14.070 --> 01:18.570
Essentially you can think of a decorator function as a function

19
01:18.570 --> 01:23.570
that's going to give additional functionality to an existing function. In order

20
01:24.360 --> 01:25.920
to really understand this,

21
01:25.980 --> 01:29.100
we have to understand a couple of other concepts as well.

22
01:29.820 --> 01:32.430
So I'm going to do a couple of demos in this Repl.it

23
01:32.850 --> 01:36.810
and if you head to this URL or find it in the course resources,

24
01:37.050 --> 01:40.140
you'll be able to see all the code that I've written in this file.

25
01:41.160 --> 01:42.600
So a long time ago,

26
01:42.630 --> 01:47.630
we learned about Python functions and we know that a function allows us to

27
01:47.820 --> 01:50.910
have specific packages of functionality,

28
01:51.420 --> 01:56.250
allows us to add inputs, to increase the reusability of the function,

29
01:56.700 --> 02:01.380
and also allows us to get outputs from the function which we can pass into

30
02:01.380 --> 02:05.610
another function or do something with it. As an example,

31
02:05.610 --> 02:09.570
we've got four very simple functions, add, subtract, multiply,

32
02:09.600 --> 02:13.890
and divide that uses all three components of a function.

33
02:15.270 --> 02:19.350
Now, what if we wanted to get a little bit fancier? Well,

34
02:19.650 --> 02:24.650
one of the things about Python functions is that they are known as first-class

35
02:25.680 --> 02:26.513
objects,

36
02:26.550 --> 02:31.550
which basically means that you can pass a function around as an argument,

37
02:32.640 --> 02:37.440
just like what you could do with an integer, a string or a float, it's treated

38
02:37.710 --> 02:38.670
identically.

39
02:39.240 --> 02:44.240
That means we can take these functions and we can build another function that

40
02:44.910 --> 02:49.290
uses these functions. Let's say I create a calculate function

41
02:49.410 --> 02:51.870
which takes a calc_function

42
02:52.320 --> 02:54.900
and then the n1 and n2.

43
02:55.590 --> 02:57.630
Inside this calculate function,

44
02:57.960 --> 03:02.860
I'm going to call the function that was passed in and give it the values

45
03:02.950 --> 03:06.670
n1 and n2 that was also passed in.

46
03:07.330 --> 03:10.120
So now when I call the calculate function,

47
03:10.150 --> 03:15.010
I'm going to pass in the name of one of these functions and then some numbers.

48
03:15.370 --> 03:20.140
Those numbers are gonna become the input for this specified function

49
03:20.500 --> 03:24.760
and then we're going to return the result of that calculation.

50
03:25.420 --> 03:26.980
So now lower down,

51
03:27.010 --> 03:32.010
I can call my calculate function, pass in the name of a function

52
03:32.620 --> 03:37.300
so for example our multiply function, and then pass in some numbers,

53
03:37.360 --> 03:42.220
for example, two and three. Now let the output that's returned

54
03:42.490 --> 03:43.690
be our results

55
03:43.840 --> 03:48.840
and let's go ahead and print this result. And you can see we get six.

56
03:50.260 --> 03:54.670
So basically it has now multiplied two by three. Now,

57
03:54.700 --> 03:58.210
if I change this to one of the other functions, add,

58
03:58.750 --> 04:03.520
and I run this again, you can see instead of six, I'm now getting five.

59
04:04.240 --> 04:09.240
The ability for us to treat functions as first-class objects basically means

60
04:10.120 --> 04:14.080
that we can pass them around as if they were just any other argument

61
04:14.380 --> 04:17.770
like a number or a string or a floating point number.

62
04:18.160 --> 04:23.160
And then later we can activate them by adding the brackets around them and then

63
04:23.470 --> 04:27.790
any necessary inputs. Now, the next concept

64
04:27.820 --> 04:29.890
which you might've come across

65
04:29.980 --> 04:34.930
but we haven't really used it a lot is the concept of nested functions.

66
04:35.740 --> 04:39.520
Functions can also be nested inside other functions.

67
04:40.030 --> 04:43.750
For example, if I create a function called outer_function

68
04:45.190 --> 04:49.570
and this function is just going to print and say,

69
04:49.600 --> 04:54.130
I'm outer. Now inside this outer_function,

70
04:54.460 --> 04:57.970
I could create another function. So notice the indentation here

71
04:58.270 --> 05:03.270
means that this function is now created inside this function and I'll call it

72
05:03.430 --> 05:06.400
the nested_function.

73
05:08.020 --> 05:13.020
So this function is simply going to print I'm

74
05:15.250 --> 05:16.083
inner.

75
05:16.780 --> 05:21.070
And now we have the problem of trying to call this function. Now,

76
05:21.100 --> 05:24.850
because this function was declared inside this function,

77
05:25.240 --> 05:30.240
its scope means that it's only accessible inside the confines of this function.

78
05:31.630 --> 05:34.750
So if we were to go outside of the function, so by

79
05:34.750 --> 05:39.400
indenting back to the beginning and we try to call this nested function,

80
05:39.730 --> 05:42.490
then it's actually not going to work.

81
05:42.910 --> 05:47.410
We're going to get a name error. It's not defined. However,

82
05:47.410 --> 05:52.410
if we call this function inside this outer_function,

83
05:53.680 --> 05:57.070
then it will now no longer generate an error.

84
05:57.920 --> 06:02.920
So let's go ahead and trigger the outer_function by calling it in our main.

85
06:04.670 --> 06:09.320
py. And when I run this, you can see it says I'm outer

86
06:09.770 --> 06:11.270
and then it says I'm inner.

87
06:12.170 --> 06:17.170
So this first gets executed and then this. And this I'm inner is being

88
06:17.300 --> 06:21.650
printed when this line is being evaluated. Now,

89
06:22.250 --> 06:27.250
one of the other things you could do is you can actually return a function from

90
06:28.280 --> 06:29.150
another function.

91
06:29.380 --> 06:30.213
<v 1>Right.</v>

92
06:32.050 --> 06:35.920
<v 0>Functions can actually be returned from other functions.</v>

93
06:36.370 --> 06:41.370
So if I make a copy of this previous function right here and comment out this

94
06:42.430 --> 06:45.850
other function and all the steps before,

95
06:46.330 --> 06:47.163
<v 1>...</v>

96
06:54.850 --> 06:57.430
<v 0>and we only have this bit of active code,</v>

97
06:57.850 --> 07:01.720
then you can see that instead of calling this nested_function here,

98
07:02.170 --> 07:04.540
I could also return it as the output.

99
07:05.050 --> 07:09.490
But the important part here is I'm going to get rid of the parentheses

100
07:09.610 --> 07:13.720
which means I'm no longer activating that function right here.

101
07:14.560 --> 07:17.440
So now when I call this outer_function,

102
07:17.830 --> 07:22.830
the output that this line is going to evaluate to is going to become the nested_

103
07:23.770 --> 07:28.390
function. So you could almost store it inside a variable.

104
07:28.480 --> 07:31.570
So let's say I create a variable called inner_function

105
07:31.900 --> 07:34.840
which is equal to the output of the outer_function

106
07:34.870 --> 07:39.100
which is basically this nested_function that's being returned. Well

107
07:39.100 --> 07:41.890
then, not only can I trigger the outer_function

108
07:42.100 --> 07:44.950
which is just going to give me I'm outer,

109
07:45.490 --> 07:50.490
now I can also trigger the inner_function separately by calling it

110
07:51.100 --> 07:54.610
and then adding the activator which is the parentheses.

111
07:55.900 --> 07:59.470
So now it says I'm outer after it evaluates this line,

112
07:59.830 --> 08:03.070
I'm inner after it evaluates this line. Now,

113
08:03.100 --> 08:04.900
if this is confusing to you,

114
08:04.960 --> 08:09.400
I recommend heading over to the course resources where I've got a link to this

115
08:09.490 --> 08:14.350
Python Tutor where I've entered all the code that we've seen just now

116
08:14.830 --> 08:17.800
and we can execute this code line by line.

117
08:18.340 --> 08:22.390
So you can see that the first thing that happens is it looks at this outer_

118
08:22.390 --> 08:26.740
function and it creates a reference to that function. Now

119
08:26.740 --> 08:31.740
next, it's on this line where our outer_function is actually being executed

120
08:32.650 --> 08:34.780
because it has the parentheses at the end.

121
08:35.170 --> 08:39.370
So now it's actually going to go inside this outer function and go through it

122
08:39.370 --> 08:44.370
line by line where it prints I'm outer and then sets up a reference to this second

123
08:45.610 --> 08:48.400
function, which is the nested_function.

124
08:49.270 --> 08:52.840
The nested_function can now be called by its name

125
08:52.840 --> 08:57.180
which is nested_function. But the very end of the outer_function,

126
08:57.300 --> 09:01.830
that function is going to be the return value. So it's going to be outputted.

127
09:02.640 --> 09:03.390
Finally,

128
09:03.390 --> 09:08.390
we get to the end of this line nine and we set up a reference from this variable

129
09:09.570 --> 09:14.400
called inner_function to this nested_function. And finally,

130
09:14.400 --> 09:18.120
when we get to the line 10 we trigger that function.

131
09:18.210 --> 09:22.560
So here is our inner_function which points to this nested function

132
09:22.860 --> 09:24.930
and so when we trigger this inner_function,

133
09:25.230 --> 09:28.440
it's the same as triggering the nested_function.

134
09:28.800 --> 09:32.520
And that is when we end up going into this function

135
09:32.820 --> 09:35.190
and printing out what it says inside.

136
09:35.820 --> 09:40.320
Have a play around with that to fully get to grips with all the things that you

137
09:40.320 --> 09:41.760
can do with a function.

138
09:42.930 --> 09:47.490
And once you're happy with all of this and you've reviewed it and you understand

139
09:47.490 --> 09:48.630
everything that's going on,

140
09:48.960 --> 09:52.800
then you've got the foundations to head over to the next lesson where we're

141
09:52.800 --> 09:55.620
going to talk about Python decorators.