1
00:00:05,180 --> 00:00:06,000
Before we get back to

2
00:00:06,000 --> 00:00:08,380
subclassing the tkintern listbox,

3
00:00:08,380 --> 00:00:10,590
there's another way of specifying parameters,

4
00:00:10,590 --> 00:00:11,970
that we need to look at

5
00:00:11,970 --> 00:00:15,870
and that's the **kwargs or kw args, and in fact

6
00:00:15,870 --> 00:00:18,620
this is the one that we need to use in our subclass.

7
00:00:18,620 --> 00:00:22,020
Now, it works in the same way as packing a variable number

8
00:00:22,020 --> 00:00:24,320
of elements of arguments into a tuple,

9
00:00:24,320 --> 00:00:26,730
but this time we need to pack a variable number

10
00:00:26,730 --> 00:00:29,390
of named arguments, or keyword arguments,

11
00:00:29,390 --> 00:00:32,200
hence kw args or kwargs.

12
00:00:32,200 --> 00:00:34,960
Now, we've used functions, that have keyword arguments

13
00:00:34,960 --> 00:00:38,890
before and the one we've used most is the print function.

14
00:00:38,890 --> 00:00:41,480
So, I'm gonna clear out all this code

15
00:00:41,480 --> 00:00:44,880
in our **kwargs file and just go back

16
00:00:44,880 --> 00:00:47,630
to a simple print of hello world.

17
00:00:51,140 --> 00:00:53,970
Now, if we Control click on the print function

18
00:00:53,970 --> 00:00:56,700
or command, if you're on a Mac,

19
00:00:56,700 --> 00:00:58,410
you can see there that it specifies

20
00:00:58,410 --> 00:01:01,040
three named, or keyword parameters.

21
00:01:01,040 --> 00:01:04,560
Now this looks slightly different if you're using Python 2,

22
00:01:04,560 --> 00:01:07,590
and the future version of print, so if that's the case,

23
00:01:07,590 --> 00:01:09,970
just follow me in the video, because everything works

24
00:01:09,970 --> 00:01:12,120
the same, it's just your version of print

25
00:01:12,120 --> 00:01:13,890
that's a little bit different.

26
00:01:13,890 --> 00:01:16,550
So we've used this end parameter in the past

27
00:01:16,550 --> 00:01:19,400
to suppress new lines, when we want several things

28
00:01:19,400 --> 00:01:21,630
to print on the same line.

29
00:01:21,630 --> 00:01:23,860
We've also used the file parameter as well.

30
00:01:23,860 --> 00:01:26,290
Over here we've got it currently set to file equals none.

31
00:01:26,290 --> 00:01:29,140
It's again line number 476.

32
00:01:29,140 --> 00:01:31,920
We use that when we write text data to a file on disc.

33
00:01:31,920 --> 00:01:34,540
So, these are keyword arguments

34
00:01:34,540 --> 00:01:37,270
and we wrote our own methods to use them, if you recall

35
00:01:37,270 --> 00:01:42,160
in the object oriented programming section of the course.

36
00:01:42,160 --> 00:01:44,760
Up until now, we've dealt with keyword arguments,

37
00:01:44,760 --> 00:01:46,750
that have default values,

38
00:01:46,750 --> 00:01:49,450
so if we don't provide a sep argument, for example,

39
00:01:49,450 --> 00:01:51,920
it defaults to a space

40
00:01:51,920 --> 00:01:54,910
and similarly, the end argument, you can see here,

41
00:01:54,910 --> 00:01:56,790
it defaults to a new line character

42
00:01:56,790 --> 00:02:00,390
and the file argument, you can see here, defaults to none.

43
00:02:00,390 --> 00:02:04,270
But what happens if we don't wanna provide defaults though?

44
00:02:04,270 --> 00:02:07,350
Now, that might seem like a daft question.

45
00:02:07,350 --> 00:02:09,930
If these arguments are used, then surely they must have

46
00:02:09,930 --> 00:02:12,500
some value, even if that value is none.

47
00:02:12,500 --> 00:02:15,590
Well, the thing is we may not know what those defaults are

48
00:02:15,590 --> 00:02:17,470
and perhaps more importantly,

49
00:02:17,470 --> 00:02:20,760
we often don't want to care what they are.

50
00:02:20,760 --> 00:02:22,940
So let's actually see an example to understand

51
00:02:22,940 --> 00:02:27,130
why we don't necessarily want to specify default values.

52
00:02:27,130 --> 00:02:30,420
So to do that, I'm going to just close the builtins.py,

53
00:02:30,420 --> 00:02:32,190
go back to our **dorarg

54
00:02:32,190 --> 00:02:35,820
and I'm going to use an exercise from a previous video,

55
00:02:35,820 --> 00:02:38,550
one that prints the words backwards.

56
00:02:38,550 --> 00:02:40,920
So I'm going to just type it in quickly,

57
00:02:40,920 --> 00:02:42,750
so def print_backwards

58
00:02:45,470 --> 00:02:46,390
and **args,

59
00:02:49,690 --> 00:02:51,110
for word in args,

60
00:02:53,790 --> 00:02:56,790
like so, ::-1 in square brackets, :,

61
00:02:57,760 --> 00:03:00,260
then we're gonna do print word

62
00:03:01,970 --> 00:03:04,350
and in square brackets again,

63
00:03:04,350 --> 00:03:05,180
::-1

64
00:03:07,130 --> 00:03:08,620
comma end=

65
00:03:08,620 --> 00:03:11,150
and in double quotes, sorry, in single quotes,

66
00:03:11,150 --> 00:03:14,100
a space up to the end=, and that's it for our method

67
00:03:14,100 --> 00:03:15,130
and in terms of calling it,

68
00:03:15,130 --> 00:03:17,480
let's just write print_backwards,

69
00:03:17,480 --> 00:03:20,180
I'm gonna pass the parameters

70
00:03:20,180 --> 00:03:21,360
hello

71
00:03:21,360 --> 00:03:22,190
planet

72
00:03:23,080 --> 00:03:23,910
earth,

73
00:03:26,100 --> 00:03:27,620
take

74
00:03:27,620 --> 00:03:29,020
me

75
00:03:29,020 --> 00:03:30,380
to

76
00:03:30,380 --> 00:03:31,210
your

77
00:03:32,410 --> 00:03:33,240
leader.

78
00:03:35,010 --> 00:03:37,910
Alright, so this is just basically a modified version

79
00:03:37,910 --> 00:03:40,770
of the print function, so I think,

80
00:03:40,770 --> 00:03:42,170
well, actually we'll just run this first

81
00:03:42,170 --> 00:03:44,280
to make sure that it in fact does work

82
00:03:44,280 --> 00:03:46,860
and you can see that we've got it working quite nicely.

83
00:03:46,860 --> 00:03:49,520
Hello planet earth, take me to your leader,

84
00:03:49,520 --> 00:03:51,450
you can see that's all showing backwards,

85
00:03:51,450 --> 00:03:53,540
which is what we tried to do.

86
00:03:53,540 --> 00:03:55,670
So what we've done here is basically

87
00:03:55,670 --> 00:03:57,910
a modified version of the print function.

88
00:03:57,910 --> 00:04:00,160
So that said, I think it would be nice

89
00:04:00,160 --> 00:04:02,870
if it behaved the same as the real print function.

90
00:04:02,870 --> 00:04:05,450
For example, we should print it to a file,

91
00:04:05,450 --> 00:04:07,590
if that's what the user wants to do with it.

92
00:04:07,590 --> 00:04:10,890
So that's actually easy, we just add a named parameter,

93
00:04:10,890 --> 00:04:13,720
then pass that on to the builtin function.

94
00:04:13,720 --> 00:04:16,300
So to do that, we come up here after the args.

95
00:04:16,300 --> 00:04:20,459
We've defined the *args, we'll put file=None,

96
00:04:21,630 --> 00:04:24,850
then for the print line, after the end=,

97
00:04:24,850 --> 00:04:29,260
two single quotes and a space, we put file=file.

98
00:04:29,260 --> 00:04:30,890
So firstly, we can try to run an as is

99
00:04:30,890 --> 00:04:32,360
to make sure it still works.

100
00:04:32,360 --> 00:04:34,600
No change to functionality there,

101
00:04:34,600 --> 00:04:36,520
but now that we've introduced file,

102
00:04:36,520 --> 00:04:38,660
we can actually print to a file if we want to.

103
00:04:38,660 --> 00:04:42,130
So to do that, we can then change the code here

104
00:04:42,130 --> 00:04:44,710
and put with open backwards.txt

105
00:04:48,980 --> 00:04:52,480
and mode w in single quotes as backwards:,

106
00:04:54,300 --> 00:04:58,150
and then on the end of the line there

107
00:04:58,150 --> 00:05:01,810
we can put comma file=backwards.

108
00:05:01,810 --> 00:05:05,870
So now if we do that, and we need to indent that

109
00:05:05,870 --> 00:05:07,650
and if we run that, we should find

110
00:05:07,650 --> 00:05:09,750
backwards.txt gets created.

111
00:05:09,750 --> 00:05:11,240
You can see, it appeared up here

112
00:05:11,240 --> 00:05:13,300
and if we just double-click that, we're now seeing

113
00:05:13,300 --> 00:05:16,300
hello planet earth take me to your leader showing.

114
00:05:16,300 --> 00:05:18,260
Alright, so that's working well.

115
00:05:18,260 --> 00:05:20,060
I had an extra space there, by the way,

116
00:05:20,060 --> 00:05:21,370
I'll get rid of that in case you were wondering

117
00:05:21,370 --> 00:05:23,720
why there was an extra space there.

118
00:05:23,720 --> 00:05:25,830
That was easy, but the print function

119
00:05:25,830 --> 00:05:28,430
only defines three keyword parameters,

120
00:05:28,430 --> 00:05:30,210
so we'd only have to code it

121
00:05:30,210 --> 00:05:32,170
for three in our function definition.

122
00:05:32,170 --> 00:05:33,890
In fact, we'd only have to code it for two,

123
00:05:33,890 --> 00:05:36,670
because we force the end to be a space,

124
00:05:36,670 --> 00:05:39,680
so that all the words printed are printed on the same line,

125
00:05:39,680 --> 00:05:42,370
so that's our definition there, you can see end calling,

126
00:05:42,370 --> 00:05:44,810
define the end too up into space.

127
00:05:44,810 --> 00:05:47,100
Now in the case of the listbox class, for example,

128
00:05:47,100 --> 00:05:49,000
there are a lot of named arguments,

129
00:05:49,000 --> 00:05:51,960
that we can provide when creating a new listbox,

130
00:05:51,960 --> 00:05:55,210
things like background, font, the highlight colour,

131
00:05:55,210 --> 00:05:57,010
and the highlight thickness.

132
00:05:57,010 --> 00:05:59,220
There are about 22 different parameters,

133
00:05:59,220 --> 00:06:01,590
that we'd actually have to match in our nip method,

134
00:06:01,590 --> 00:06:03,980
if we wanna provide all the same options.

135
00:06:03,980 --> 00:06:05,260
Now that's bad enough, but what if say,

136
00:06:05,260 --> 00:06:07,930
the next version of the listbox has a new option?

137
00:06:07,930 --> 00:06:09,800
Our class would know nothing about it,

138
00:06:09,800 --> 00:06:12,070
so users of our subclass then wouldn't be able

139
00:06:12,070 --> 00:06:14,770
to take advantage of these latest features.

140
00:06:14,770 --> 00:06:17,100
Now fortunately, there's an easier way

141
00:06:17,100 --> 00:06:21,900
and this is where the **kw args or kwargs actually comes in.

142
00:06:21,900 --> 00:06:23,820
Now we've seen that the asterix can be used

143
00:06:23,820 --> 00:06:25,650
to unpack a tuple or a list,

144
00:06:25,650 --> 00:06:28,890
but the double asterix operator, **,

145
00:06:28,890 --> 00:06:31,450
unpacks a dictionary in the same way.

146
00:06:31,450 --> 00:06:34,410
Now a dictionary is used because keyword arguments

147
00:06:34,410 --> 00:06:37,560
are specified as a keyword and a value

148
00:06:37,560 --> 00:06:40,700
and that's exactly what you have in the dictionary,

149
00:06:40,700 --> 00:06:42,260
a key and a value.

150
00:06:42,260 --> 00:06:43,770
So what all this means is that we can scoop up

151
00:06:43,770 --> 00:06:46,060
all the keyword arguments and pass the whole lot

152
00:06:46,060 --> 00:06:48,570
on to the print function.

153
00:06:48,570 --> 00:06:50,240
So let's have a go at doing that.

154
00:06:50,240 --> 00:06:53,130
We're gonna come back here and remove the file=None,

155
00:06:53,130 --> 00:06:57,300
and instead what we're gonna do is put **kwargs or kw args,

156
00:06:58,740 --> 00:07:02,170
like so, and then we come down here

157
00:07:02,170 --> 00:07:05,150
and after the end, instead of file=file,

158
00:07:05,150 --> 00:07:06,570
we replace that to, or with rather,

159
00:07:06,570 --> 00:07:08,740
**kwargs or kw args again,

160
00:07:10,260 --> 00:07:12,580
and just to be sure,

161
00:07:12,580 --> 00:07:14,670
we'll just delete the backwards.txt file

162
00:07:14,670 --> 00:07:18,830
to confirm it is being created with this new code.

163
00:07:19,870 --> 00:07:24,330
So if you run this, we can see that it still worked

164
00:07:24,330 --> 00:07:26,200
and backwards.txt got created, and in fact

165
00:07:26,200 --> 00:07:28,420
there's no space there like there was before,

166
00:07:28,420 --> 00:07:31,410
so it confirmation that has worked nicely.

167
00:07:31,410 --> 00:07:34,430
So here what we've done is on line 1,

168
00:07:34,430 --> 00:07:38,430
is we've defined our function to accept **kwargs

169
00:07:38,430 --> 00:07:40,100
and whatever appears in there

170
00:07:40,100 --> 00:07:42,320
is just passed onto the print function

171
00:07:42,320 --> 00:07:44,340
and you can see that happening on line 3.

172
00:07:44,340 --> 00:07:45,990
So that is pretty cool.

173
00:07:45,990 --> 00:07:48,210
The calling code is free to add as many

174
00:07:48,210 --> 00:07:50,880
keyword arguments as print will accept

175
00:07:50,880 --> 00:07:52,760
and we don't have to worry about what they are,

176
00:07:52,760 --> 00:07:55,800
nor do we need to worry what their default values are.

177
00:07:55,800 --> 00:07:58,830
Now once again, we could call a parameter anything,

178
00:07:58,830 --> 00:08:01,290
but the convention here is to use

179
00:08:01,290 --> 00:08:03,920
kw args or kwargs as the name.

180
00:08:03,920 --> 00:08:06,720
Now let's check what's in kwargs,

181
00:08:06,720 --> 00:08:09,370
by printing it out before you do any processing.

182
00:08:09,370 --> 00:08:11,710
So we can add a line two to do that

183
00:08:11,710 --> 00:08:14,460
then we'll just do a print kwargs

184
00:08:15,800 --> 00:08:18,490
and if we run this, you can see there

185
00:08:18,490 --> 00:08:20,390
that kwarg is just a dictionary,

186
00:08:20,390 --> 00:08:22,170
it's got an entry with the key file

187
00:08:22,170 --> 00:08:25,290
and the value is our file object.

188
00:08:25,290 --> 00:08:27,390
We can see the name backwards, like txt there

189
00:08:27,390 --> 00:08:30,330
and mode equals w in the printed representation

190
00:08:30,330 --> 00:08:32,490
of the file down here in the Run window.

191
00:08:32,490 --> 00:08:34,640
Now if the print function changes in the future,

192
00:08:34,640 --> 00:08:36,789
to have additional keyword arguments

193
00:08:36,789 --> 00:08:39,299
our code will still work fine.

194
00:08:39,299 --> 00:08:40,760
The user can specify them

195
00:08:40,760 --> 00:08:43,070
when calling our print_backwards function,

196
00:08:43,070 --> 00:08:46,000
and we just pass them on to the builtin print.

197
00:08:46,000 --> 00:08:48,670
That means that we can handle functions in classes,

198
00:08:48,670 --> 00:08:50,160
that take keyword arguments,

199
00:08:50,160 --> 00:08:52,000
that we don't have to know or care about

200
00:08:52,000 --> 00:08:54,800
and that obviously makes life a lot easier.

201
00:08:54,800 --> 00:08:57,010
However with that said, there's a slight problem

202
00:08:57,010 --> 00:08:58,830
with this code and it's easy to fix

203
00:08:58,830 --> 00:09:01,130
and that's gonna be your next challenge.

204
00:09:01,130 --> 00:09:03,310
But I'll end the video here.

205
00:09:03,310 --> 00:09:04,670
In the next video, we'll have a look

206
00:09:04,670 --> 00:09:06,140
and see what the problem is first

207
00:09:06,140 --> 00:09:07,490
and then we'll get you to look at it,

208
00:09:07,490 --> 00:09:09,450
by way of a challenge to solve that problem.

209
00:09:09,450 --> 00:09:12,280
So I'll see you in the next video.

