1
1

00:00:01,970  -->  00:00:03,720
<v Instructor>Hi guys and welcome back.</v>
2

2

00:00:03,720  -->  00:00:07,200
In this video we're going to talk about decorators.
3

3

00:00:07,200  -->  00:00:10,200
A decorator is an advanced Python construct
4

4

00:00:10,200  -->  00:00:13,250
that is frequently confusing for beginners
5

5

00:00:13,250  -->  00:00:14,970
and with good reason.
6

6

00:00:14,970  -->  00:00:16,160
It's a bit of a weird one
7

7

00:00:16,160  -->  00:00:20,550
but we're gonna try our best to cover it in simple terms
8

8

00:00:20,550  -->  00:00:22,870
and then move over to our application
9

9

00:00:22,870  -->  00:00:24,343
so that it's a bit clearer.
10

10

00:00:25,420  -->  00:00:27,850
Imagine you've got a Python dictionary
11

11

00:00:27,850  -->  00:00:31,240
like this one that says something like, username
12

12

00:00:31,240  -->  00:00:32,993
and access level,
13

13

00:00:33,960  -->  00:00:35,540
let's say is admin.
14

14

00:00:35,540  -->  00:00:36,610
So you've got this dictionary
15

15

00:00:36,610  -->  00:00:39,620
and by the way I'm just here on a Python interpreter
16

16

00:00:39,620  -->  00:00:41,840
and so every line of code that I'm executing
17

17

00:00:41,840  -->  00:00:44,030
is just instantly running.
18

18

00:00:44,030  -->  00:00:45,520
So now the variable is defined,
19

19

00:00:45,520  -->  00:00:47,290
if you just type the variable name out,
20

20

00:00:47,290  -->  00:00:49,743
this tells you the values of it.
21

21

00:00:50,782  -->  00:00:51,653
And by the way so you know
22

22

00:00:51,653  -->  00:00:54,720
that if you've taken our complete Python course,
23

23

00:00:54,720  -->  00:00:56,340
this is gonna look very familiar.
24

24

00:00:56,340  -->  00:00:59,093
It's essentially the same example.
25

25

00:01:01,400  -->  00:01:05,130
Now let's say that you have another function,
26

26

00:01:05,130  -->  00:01:07,283
which I'm gonna call my function.
27

27

00:01:08,640  -->  00:01:12,820
And it just returns like the password for an admin panel.
28

28

00:01:12,820  -->  00:01:15,020
So the password for the admin panel
29

29

00:01:15,020  -->  00:01:18,273
is 1234, very secure password.
30

30

00:01:19,280  -->  00:01:21,840
Now whenever you call my function,
31

31

00:01:21,840  -->  00:01:25,263
it just tells you the password for the admin panel is 1234.
32

32

00:01:27,620  -->  00:01:31,373
Even if somebody comes along that isn't this user,
33

33

00:01:32,240  -->  00:01:34,070
they can still run my function
34

34

00:01:34,070  -->  00:01:36,890
and they can still get the password for the admin panel.
35

35

00:01:36,890  -->  00:01:38,320
So we wanna stop that.
36

36

00:01:38,320  -->  00:01:40,900
We wanna make sure that only users
37

37

00:01:40,900  -->  00:01:43,660
that have an access level of admin
38

38

00:01:43,660  -->  00:01:45,843
are able to run my function.
39

39

00:01:47,000  -->  00:01:48,780
So how do you do that?
40

40

00:01:48,780  -->  00:01:53,780
Well, you can say, if user access level is admin,
41

41

00:01:55,560  -->  00:01:57,193
then you can run my function,
42

42

00:01:58,250  -->  00:01:59,790
otherwise you can't.
43

43

00:01:59,790  -->  00:02:01,360
If you do this,
44

44

00:02:01,360  -->  00:02:03,190
I mean if you actually run this if statement,
45

45

00:02:03,190  -->  00:02:05,450
it tells you the password because the user
46

46

00:02:05,450  -->  00:02:08,370
does have an access level of admin.
47

47

00:02:08,370  -->  00:02:11,440
Let's try to put this inside a function,
48

48

00:02:11,440  -->  00:02:14,680
so that we can get the value out of it
49

49

00:02:14,680  -->  00:02:16,940
already with the comparison
50

50

00:02:16,940  -->  00:02:18,693
of the access level being executed.
51

51

00:02:20,370  -->  00:02:25,073
So this can be called something like, get password if admin.
52

52

00:02:26,728  -->  00:02:28,730
And what this will do is it will say exactly
53

53

00:02:28,730  -->  00:02:31,660
what we have there, if the user has an access level
54

54

00:02:33,940  -->  00:02:36,583
of admin then we're gonna run my function.
55

55

00:02:38,390  -->  00:02:40,340
Otherwise we're not gonna run anything.
56

56

00:02:41,220  -->  00:02:42,710
But here's the thing,
57

57

00:02:42,710  -->  00:02:46,220
what happens when you run this function?
58

58

00:02:46,220  -->  00:02:49,740
Remember, my function returns a string,
59

59

00:02:49,740  -->  00:02:52,170
it returns the string that tells you the password,
60

60

00:02:52,170  -->  00:02:53,493
it doesn't print it out.
61

61

00:02:54,360  -->  00:02:57,963
So when you run get password if admin,
62

62

00:02:58,830  -->  00:03:00,500
you get nothing.
63

63

00:03:00,500  -->  00:03:01,860
Why is that?
64

64

00:03:01,860  -->  00:03:04,740
Because this function here executed
65

65

00:03:05,740  -->  00:03:08,750
but we didn't return its value,
66

66

00:03:08,750  -->  00:03:11,620
we didn't return the value that this function returned
67

67

00:03:11,620  -->  00:03:15,070
so actually get password if admin returns none,
68

68

00:03:15,070  -->  00:03:17,713
that's the default for all Python functions.
69

69

00:03:19,870  -->  00:03:21,100
So what can you do?
70

70

00:03:21,100  -->  00:03:24,360
Well, you can say again, get password if admin,
71

71

00:03:24,360  -->  00:03:26,370
we gonna define it again but now we're gonna say,
72

72

00:03:26,370  -->  00:03:30,253
if the user access level is admin,
73

73

00:03:31,220  -->  00:03:33,063
we're gonna return my function.
74

74

00:03:35,800  -->  00:03:36,680
Okay?
75

75

00:03:36,680  -->  00:03:37,890
So let's do it again.
76

76

00:03:37,890  -->  00:03:42,890
Get password if admin, and now we get the result.
77

77

00:03:44,350  -->  00:03:45,183
Perfect.
78

78

00:03:45,183  -->  00:03:47,113
So is this a decorator?
79

79

00:03:48,080  -->  00:03:49,040
Not yet.
80

80

00:03:49,040  -->  00:03:50,250
This is not quite a decorator
81

81

00:03:50,250  -->  00:03:52,610
but it does exactly the same thing
82

82

00:03:52,610  -->  00:03:54,223
that a decorator would do.
83

83

00:03:55,222  -->  00:03:59,260
However, this still has a problem.
84

84

00:03:59,260  -->  00:04:01,760
Which is that anybody comes into this code
85

85

00:04:01,760  -->  00:04:03,510
and can say, you know, my function.
86

86

00:04:04,420  -->  00:04:06,900
And then we don't check whether their access level
87

87

00:04:06,900  -->  00:04:07,883
is admin or not.
88

88

00:04:09,200  -->  00:04:10,033
What have we done?
89

89

00:04:10,033  -->  00:04:13,520
We've actually created a new function that does the checking
90

90

00:04:13,520  -->  00:04:17,130
but we've still left the old function unchecked.
91

91

00:04:17,130  -->  00:04:20,070
Another example code.
92

92

00:04:20,070  -->  00:04:23,240
We're gonna say something like user has permission
93

93

00:04:24,130  -->  00:04:26,740
and we're gonna pass to it a function.
94

94

00:04:26,740  -->  00:04:28,453
I'm just calling it func for now.
95

95

00:04:30,730  -->  00:04:33,720
What we wanna do, is we wanna run this function
96

96

00:04:34,830  -->  00:04:38,573
if the user has the permission.
97

97

00:04:40,220  -->  00:04:45,220
So we'll say, if user access level is admin.
98

98

00:04:52,520  -->  00:04:55,540
Now we wanna run the function
99

99

00:04:55,540  -->  00:04:59,190
so we will say return func, okay?
100

100

00:04:59,190  -->  00:05:02,600
Pretty much exactly the same as we had up here.
101

101

00:05:02,600  -->  00:05:04,400
But if we say,
102

102

00:05:04,400  -->  00:05:09,283
my function equal user has permission with my function,
103

103

00:05:10,300  -->  00:05:14,080
what happens now is that my function
104

104

00:05:14,920  -->  00:05:18,950
which used to be this unsecured function up here,
105

105

00:05:18,950  -->  00:05:23,430
my function has now become the result of running
106

106

00:05:23,430  -->  00:05:27,223
user has permission with my function passed into it.
107

107

00:05:28,200  -->  00:05:30,300
So if we go just up here,
108

108

00:05:30,300  -->  00:05:32,620
we can see what happens when you do that.
109

109

00:05:32,620  -->  00:05:35,300
My function becomes func,
110

110

00:05:35,300  -->  00:05:38,300
and then we check if the user's access level is admin
111

111

00:05:38,300  -->  00:05:41,730
then return the value of running func.
112

112

00:05:41,730  -->  00:05:43,620
When you run my function you get,
113

113

00:05:43,620  -->  00:05:46,090
password for admin panel is 1234.
114

114

00:05:46,090  -->  00:05:49,410
So user has permission will return,
115

115

00:05:49,410  -->  00:05:51,590
password for admin panel is 1234
116

116

00:05:51,590  -->  00:05:54,690
because of the time that we run this line,
117

117

00:05:54,690  -->  00:05:58,390
the user had an admin access level.
118

118

00:05:58,390  -->  00:06:02,120
So now, my function is no longer a function,
119

119

00:06:02,120  -->  00:06:07,000
now my function is the result of running the check
120

120

00:06:07,000  -->  00:06:08,910
and returning this function.
121

121

00:06:08,910  -->  00:06:11,670
This is not what we wanted to do.
122

122

00:06:11,670  -->  00:06:13,863
So I'm gonna clear it a bit,
123

123

00:06:14,950  -->  00:06:16,800
and then we're gonna copy this again.
124

124

00:06:19,000  -->  00:06:21,347
We're gonna once again, get my function
125

125

00:06:21,347  -->  00:06:23,640
and we're gonna make it into a function once again,
126

126

00:06:23,640  -->  00:06:26,980
in order for us to get to our final example.
127

127

00:06:26,980  -->  00:06:30,990
So now, my function gives us the password
128

128

00:06:30,990  -->  00:06:33,490
for the admin panel is 1234 but it is a function
129

129

00:06:33,490  -->  00:06:34,673
we do have to run it.
130

130

00:06:35,740  -->  00:06:37,670
What we're gonna do now is we're gonna define
131

131

00:06:37,670  -->  00:06:40,607
another user has permission function
132

132

00:06:40,607  -->  00:06:43,740
and it's also gonna take in func,
133

133

00:06:43,740  -->  00:06:46,800
a function as a parameter.
134

134

00:06:46,800  -->  00:06:49,420
But inside of this function,
135

135

00:06:49,420  -->  00:06:51,513
we're going to define another function.
136

136

00:06:54,110  -->  00:06:56,540
Inside this function, we're gonna say,
137

137

00:06:56,540  -->  00:07:01,540
if user access level is admin,
138

138

00:07:01,630  -->  00:07:03,753
then we're gonna return func.
139

139

00:07:06,340  -->  00:07:08,650
So this user has permission function
140

140

00:07:08,650  -->  00:07:10,910
actually defined a function inside of it
141

141

00:07:10,910  -->  00:07:13,090
that does the checking and runs
142

142

00:07:13,090  -->  00:07:15,623
whatever function was originally passed to it.
143

143

00:07:17,210  -->  00:07:22,080
What should user has permission do with that function?
144

144

00:07:22,080  -->  00:07:24,680
It should return it.
145

145

00:07:24,680  -->  00:07:25,830
And here's why.
146

146

00:07:25,830  -->  00:07:30,830
Now, if we run my function, it's completely unsecured
147

147

00:07:31,240  -->  00:07:35,387
but we should now say, my function is equal to user
148

148

00:07:36,420  -->  00:07:41,093
has permission with my function passed into it.
149

149

00:07:41,960  -->  00:07:44,200
So what this going to do when we run it,
150

150

00:07:44,200  -->  00:07:47,020
is it's gonna evaluate
151

151

00:07:47,020  -->  00:07:49,743
the result of running user has permission.
152

152

00:07:50,890  -->  00:07:53,870
And it's gonna replace my function
153

153

00:07:53,870  -->  00:07:56,610
with whatever that returns.
154

154

00:07:56,610  -->  00:08:01,080
So, once again, my function is gonna be passed in as func,
155

155

00:08:01,080  -->  00:08:04,300
we're gonna define another function and inside that one,
156

156

00:08:04,300  -->  00:08:06,750
we're gonna check the access level to see if it's admin
157

157

00:08:06,750  -->  00:08:09,810
and if it is, we're going to run the original function
158

158

00:08:09,810  -->  00:08:11,203
which is my function.
159

159

00:08:12,450  -->  00:08:15,680
Then we return this inner function
160

160

00:08:15,680  -->  00:08:19,560
and that is what my function becomes.
161

161

00:08:19,560  -->  00:08:23,323
So my function becomes this secure func.
162

162

00:08:25,240  -->  00:08:27,370
So if we run my function now,
163

163

00:08:27,370  -->  00:08:30,730
we get the password for the admin panel is 1234
164

164

00:08:30,730  -->  00:08:34,010
but if we define another user with say,
165

165

00:08:34,010  -->  00:08:36,403
username bob and access level,
166

166

00:08:37,670  -->  00:08:38,503
guest.
167

167

00:08:39,770  -->  00:08:43,410
And we run my function again, now you get nothing.
168

168

00:08:43,410  -->  00:08:45,960
Because the user at the time of running,
169

169

00:08:45,960  -->  00:08:48,303
did not have the appropriate access level.
170

170

00:08:49,330  -->  00:08:50,720
What we've just defined here,
171

171

00:08:50,720  -->  00:08:53,373
this is a decorator in Python.
172

172

00:08:54,300  -->  00:08:57,770
A decorator is a function that returns another function
173

173

00:08:58,650  -->  00:09:02,750
and the inner function runs the function that was passed
174

174

00:09:02,750  -->  00:09:04,743
to the decorator as an argument.
175

175

00:09:06,070  -->  00:09:07,280
And the reason for that,
176

176

00:09:07,280  -->  00:09:09,570
is because it allows us to extend
177

177

00:09:09,570  -->  00:09:11,620
the original function with extra things.
178

178

00:09:11,620  -->  00:09:14,010
In this case we are doing if the user's access level
179

179

00:09:14,010  -->  00:09:16,023
as admin will run this function.
180

180

00:09:17,750  -->  00:09:19,070
So that's what a decorator is for,
181

181

00:09:19,070  -->  00:09:21,170
a decorator is for extending the functionality
182

182

00:09:21,170  -->  00:09:22,350
of an existing function
183

183

00:09:23,370  -->  00:09:25,643
while leaving the original, unchanged.
184

184

00:09:28,490  -->  00:09:31,660
And I know that this is a bit of a strange way
185

185

00:09:31,660  -->  00:09:35,200
of looking at decorators but we're gonna now move over
186

186

00:09:35,200  -->  00:09:37,850
to our web application and you're gonna see
187

187

00:09:37,850  -->  00:09:40,430
how this applies in a real app
188

188

00:09:40,430  -->  00:09:42,260
as opposed to just example code.
189

189

00:09:42,260  -->  00:09:45,043
So please bear with me and see you on the next video.
