WEBVTT 1 00:00:00.813 --> 00:00:02.573 Before we get back to 2 00:00:02.573 --> 00:00:04.959 subclassing the tkintern listbox, 3 00:00:04.959 --> 00:00:07.160 there's another way of specifying parameters, 4 00:00:07.160 --> 00:00:08.541 that we need to look at 5 00:00:08.541 --> 00:00:12.449 and that's the **kwargs or kw args, and in fact 6 00:00:12.449 --> 00:00:15.197 this is the one that we need to use in our subclass. 7 00:00:15.197 --> 00:00:18.590 Now, it works in the same way as packing a variable number 8 00:00:18.590 --> 00:00:20.899 of elements of arguments into a tuple, 9 00:00:20.899 --> 00:00:23.305 but this time we need to pack a variable number 10 00:00:23.305 --> 00:00:25.963 of named arguments, or keyword arguments, 11 00:00:25.963 --> 00:00:28.774 hence kw args or kwargs. 12 00:00:28.774 --> 00:00:31.539 Now, we've used functions, that have keyword arguments 13 00:00:31.539 --> 00:00:35.464 before and the one we've used most is the print function. 14 00:00:35.464 --> 00:00:38.052 So, I'm gonna clear out all this code 15 00:00:38.052 --> 00:00:41.452 in our **kwargs file and just go back 16 00:00:41.452 --> 00:00:44.202 to a simple print of hello world. 17 00:00:47.716 --> 00:00:50.544 Now, if we Control click on the print function 18 00:00:50.544 --> 00:00:53.271 or command, if you're on a Mac, 19 00:00:53.271 --> 00:00:54.985 you can see there that it specifies 20 00:00:54.985 --> 00:00:57.611 three named, or keyword parameters. 21 00:00:57.611 --> 00:01:01.131 Now this looks slightly different if you're using Python 2, 22 00:01:01.131 --> 00:01:04.168 and the future version of print, so if that's the case, 23 00:01:04.168 --> 00:01:06.545 just follow me in the video, because everything works 24 00:01:06.545 --> 00:01:08.694 the same, it's just your version of print 25 00:01:08.694 --> 00:01:10.467 that's a little bit different. 26 00:01:10.467 --> 00:01:13.123 So we've used this end parameter in the past 27 00:01:13.123 --> 00:01:15.978 to suppress new lines, when we want several things 28 00:01:15.978 --> 00:01:18.207 to print on the same line. 29 00:01:18.207 --> 00:01:20.439 We've also used the file parameter as well. 30 00:01:20.439 --> 00:01:22.869 Over here we've got it currently set to file equals none. 31 00:01:22.869 --> 00:01:25.719 It's again line number 476. 32 00:01:25.719 --> 00:01:28.495 We use that when we write text data to a file on disc. 33 00:01:28.495 --> 00:01:31.110 So, these are keyword arguments 34 00:01:31.110 --> 00:01:33.842 and we wrote our own methods to use them, if you recall 35 00:01:33.842 --> 00:01:38.730 in the object oriented programming section of the course. 36 00:01:38.730 --> 00:01:41.330 Up until now, we've dealt with keyword arguments, 37 00:01:41.330 --> 00:01:43.325 that have default values, 38 00:01:43.325 --> 00:01:46.028 so if we don't provide a sep argument, for example, 39 00:01:46.028 --> 00:01:48.499 it defaults to a space 40 00:01:48.499 --> 00:01:51.487 and similarly, the end argument, you can see here, 41 00:01:51.487 --> 00:01:53.366 it defaults to a new line character 42 00:01:53.366 --> 00:01:56.966 and the file argument, you can see here, defaults to none. 43 00:01:56.966 --> 00:02:00.848 But what happens if we don't wanna provide defaults though? 44 00:02:00.848 --> 00:02:03.925 Now, that might seem like a daft question. 45 00:02:03.925 --> 00:02:06.500 If these arguments are used, then surely they must have 46 00:02:06.500 --> 00:02:09.077 some value, even if that value is none. 47 00:02:09.077 --> 00:02:12.168 Well, the thing is we may not know what those defaults are 48 00:02:12.168 --> 00:02:14.041 and perhaps more importantly, 49 00:02:14.041 --> 00:02:17.331 we often don't want to care what they are. 50 00:02:17.331 --> 00:02:19.510 So let's actually see an example to understand 51 00:02:19.510 --> 00:02:23.709 why we don't necessarily want to specify default values. 52 00:02:23.709 --> 00:02:26.990 So to do that, I'm going to just close the builtins.py, 53 00:02:26.990 --> 00:02:28.767 go back to our **dorarg 54 00:02:28.767 --> 00:02:32.397 and I'm going to use an exercise from a previous video, 55 00:02:32.397 --> 00:02:35.122 one that prints the words backwards. 56 00:02:35.122 --> 00:02:37.491 So I'm going to just type it in quickly, 57 00:02:37.491 --> 00:02:39.324 so def print_backwards 58 00:02:42.047 --> 00:02:42.964 and **args, 59 00:02:46.267 --> 00:02:47.684 for word in args, 60 00:02:50.368 --> 00:02:53.368 like so, ::-1 in square brackets, :, 61 00:02:54.334 --> 00:02:56.834 then we're gonna do print word 62 00:02:58.544 --> 00:03:00.925 and in square brackets again, 63 00:03:00.925 --> 00:03:01.758 ::-1 64 00:03:03.708 --> 00:03:05.196 comma end= 65 00:03:05.196 --> 00:03:07.721 and in double quotes, sorry, in single quotes, 66 00:03:07.721 --> 00:03:10.679 a space up to the end=, and that's it for our method 67 00:03:10.679 --> 00:03:11.700 and in terms of calling it, 68 00:03:11.700 --> 00:03:14.051 let's just write print_backwards, 69 00:03:14.051 --> 00:03:16.753 I'm gonna pass the parameters 70 00:03:16.753 --> 00:03:17.936 hello 71 00:03:17.936 --> 00:03:18.769 planet 72 00:03:19.652 --> 00:03:20.485 earth, 73 00:03:22.679 --> 00:03:24.194 take 74 00:03:24.194 --> 00:03:25.596 me 75 00:03:25.596 --> 00:03:26.950 to 76 00:03:26.950 --> 00:03:27.783 your 77 00:03:28.982 --> 00:03:29.815 leader. 78 00:03:31.580 --> 00:03:34.481 Alright, so this is just basically a modified version 79 00:03:34.481 --> 00:03:37.347 of the print function, so I think, 80 00:03:37.347 --> 00:03:38.741 well, actually we'll just run this first 81 00:03:38.741 --> 00:03:40.855 to make sure that it in fact does work 82 00:03:40.855 --> 00:03:43.434 and you can see that we've got it working quite nicely. 83 00:03:43.434 --> 00:03:46.098 Hello planet earth, take me to your leader, 84 00:03:46.098 --> 00:03:48.029 you can see that's all showing backwards, 85 00:03:48.029 --> 00:03:50.119 which is what we tried to do. 86 00:03:50.119 --> 00:03:52.245 So what we've done here is basically 87 00:03:52.245 --> 00:03:54.489 a modified version of the print function. 88 00:03:54.489 --> 00:03:56.734 So that said, I think it would be nice 89 00:03:56.734 --> 00:03:59.449 if it behaved the same as the real print function. 90 00:03:59.449 --> 00:04:02.020 For example, we should print it to a file, 91 00:04:02.020 --> 00:04:04.166 if that's what the user wants to do with it. 92 00:04:04.166 --> 00:04:07.462 So that's actually easy, we just add a named parameter, 93 00:04:07.462 --> 00:04:10.296 then pass that on to the builtin function. 94 00:04:10.296 --> 00:04:12.870 So to do that, we come up here after the args. 95 00:04:12.870 --> 00:04:17.037 We've defined the *args, we'll put file=None, 96 00:04:18.205 --> 00:04:21.428 then for the print line, after the end=, 97 00:04:21.428 --> 00:04:25.836 two single quotes and a space, we put file=file. 98 00:04:25.836 --> 00:04:27.464 So firstly, we can try to run an as is 99 00:04:27.464 --> 00:04:28.939 to make sure it still works. 100 00:04:28.939 --> 00:04:31.170 No change to functionality there, 101 00:04:31.170 --> 00:04:33.090 but now that we've introduced file, 102 00:04:33.090 --> 00:04:35.234 we can actually print to a file if we want to. 103 00:04:35.234 --> 00:04:38.700 So to do that, we can then change the code here 104 00:04:38.700 --> 00:04:41.283 and put with open backwards.txt 105 00:04:45.556 --> 00:04:49.056 and mode w in single quotes as backwards:, 106 00:04:50.876 --> 00:04:54.729 and then on the end of the line there 107 00:04:54.729 --> 00:04:58.386 we can put comma file=backwards. 108 00:04:58.386 --> 00:05:02.444 So now if we do that, and we need to indent that 109 00:05:02.444 --> 00:05:04.221 and if we run that, we should find 110 00:05:04.221 --> 00:05:06.325 backwards.txt gets created. 111 00:05:06.325 --> 00:05:07.810 You can see, it appeared up here 112 00:05:07.810 --> 00:05:09.877 and if we just double-click that, we're now seeing 113 00:05:09.877 --> 00:05:12.875 hello planet earth take me to your leader showing. 114 00:05:12.875 --> 00:05:14.834 Alright, so that's working well. 115 00:05:14.834 --> 00:05:16.633 I had an extra space there, by the way, 116 00:05:16.633 --> 00:05:17.943 I'll get rid of that in case you were wondering 117 00:05:17.943 --> 00:05:20.294 why there was an extra space there. 118 00:05:20.294 --> 00:05:22.401 That was easy, but the print function 119 00:05:22.401 --> 00:05:25.003 only defines three keyword parameters, 120 00:05:25.003 --> 00:05:26.784 so we'd only have to code it 121 00:05:26.784 --> 00:05:28.748 for three in our function definition. 122 00:05:28.748 --> 00:05:30.465 In fact, we'd only have to code it for two, 123 00:05:30.465 --> 00:05:33.248 because we force the end to be a space, 124 00:05:33.248 --> 00:05:36.255 so that all the words printed are printed on the same line, 125 00:05:36.255 --> 00:05:38.940 so that's our definition there, you can see end calling, 126 00:05:38.940 --> 00:05:41.382 define the end too up into space. 127 00:05:41.382 --> 00:05:43.675 Now in the case of the listbox class, for example, 128 00:05:43.675 --> 00:05:45.575 there are a lot of named arguments, 129 00:05:45.575 --> 00:05:48.537 that we can provide when creating a new listbox, 130 00:05:48.537 --> 00:05:51.789 things like background, font, the highlight colour, 131 00:05:51.789 --> 00:05:53.586 and the highlight thickness. 132 00:05:53.586 --> 00:05:55.790 There are about 22 different parameters, 133 00:05:55.790 --> 00:05:58.160 that we'd actually have to match in our nip method, 134 00:05:58.160 --> 00:06:00.555 if we wanna provide all the same options. 135 00:06:00.555 --> 00:06:01.838 Now that's bad enough, but what if say, 136 00:06:01.838 --> 00:06:04.508 the next version of the listbox has a new option? 137 00:06:04.508 --> 00:06:06.370 Our class would know nothing about it, 138 00:06:06.370 --> 00:06:08.643 so users of our subclass then wouldn't be able 139 00:06:08.643 --> 00:06:11.340 to take advantage of these latest features. 140 00:06:11.340 --> 00:06:13.674 Now fortunately, there's an easier way 141 00:06:13.674 --> 00:06:18.478 and this is where the **kw args or kwargs actually comes in. 142 00:06:18.478 --> 00:06:20.398 Now we've seen that the asterix can be used 143 00:06:20.398 --> 00:06:22.227 to unpack a tuple or a list, 144 00:06:22.227 --> 00:06:25.468 but the double asterix operator, **, 145 00:06:25.468 --> 00:06:28.029 unpacks a dictionary in the same way. 146 00:06:28.029 --> 00:06:30.986 Now a dictionary is used because keyword arguments 147 00:06:30.986 --> 00:06:34.131 are specified as a keyword and a value 148 00:06:34.131 --> 00:06:37.279 and that's exactly what you have in the dictionary, 149 00:06:37.279 --> 00:06:38.830 a key and a value. 150 00:06:38.830 --> 00:06:40.340 So what all this means is that we can scoop up 151 00:06:40.340 --> 00:06:42.636 all the keyword arguments and pass the whole lot 152 00:06:42.636 --> 00:06:45.146 on to the print function. 153 00:06:45.146 --> 00:06:46.816 So let's have a go at doing that. 154 00:06:46.816 --> 00:06:49.708 We're gonna come back here and remove the file=None, 155 00:06:49.708 --> 00:06:53.875 and instead what we're gonna do is put **kwargs or kw args, 156 00:06:55.311 --> 00:06:58.745 like so, and then we come down here 157 00:06:58.745 --> 00:07:01.727 and after the end, instead of file=file, 158 00:07:01.727 --> 00:07:03.143 we replace that to, or with rather, 159 00:07:03.143 --> 00:07:05.310 **kwargs or kw args again, 160 00:07:06.839 --> 00:07:09.156 and just to be sure, 161 00:07:09.156 --> 00:07:11.241 we'll just delete the backwards.txt file 162 00:07:11.241 --> 00:07:15.408 to confirm it is being created with this new code. 163 00:07:16.445 --> 00:07:20.903 So if you run this, we can see that it still worked 164 00:07:20.903 --> 00:07:22.777 and backwards.txt got created, and in fact 165 00:07:22.777 --> 00:07:24.996 there's no space there like there was before, 166 00:07:24.996 --> 00:07:27.987 so it confirmation that has worked nicely. 167 00:07:27.987 --> 00:07:31.003 So here what we've done is on line 1, 168 00:07:31.003 --> 00:07:35.000 is we've defined our function to accept **kwargs 169 00:07:35.000 --> 00:07:36.676 and whatever appears in there 170 00:07:36.676 --> 00:07:38.899 is just passed onto the print function 171 00:07:38.899 --> 00:07:40.918 and you can see that happening on line 3. 172 00:07:40.918 --> 00:07:42.566 So that is pretty cool. 173 00:07:42.566 --> 00:07:44.788 The calling code is free to add as many 174 00:07:44.788 --> 00:07:47.452 keyword arguments as print will accept 175 00:07:47.452 --> 00:07:49.334 and we don't have to worry about what they are, 176 00:07:49.334 --> 00:07:52.370 nor do we need to worry what their default values are. 177 00:07:52.370 --> 00:07:55.401 Now once again, we could call a parameter anything, 178 00:07:55.401 --> 00:07:57.866 but the convention here is to use 179 00:07:57.866 --> 00:08:00.497 kw args or kwargs as the name. 180 00:08:00.497 --> 00:08:03.294 Now let's check what's in kwargs, 181 00:08:03.294 --> 00:08:05.946 by printing it out before you do any processing. 182 00:08:05.946 --> 00:08:08.288 So we can add a line two to do that 183 00:08:08.288 --> 00:08:11.038 then we'll just do a print kwargs 184 00:08:12.376 --> 00:08:15.061 and if we run this, you can see there 185 00:08:15.061 --> 00:08:16.968 that kwarg is just a dictionary, 186 00:08:16.968 --> 00:08:18.746 it's got an entry with the key file 187 00:08:18.746 --> 00:08:21.869 and the value is our file object. 188 00:08:21.869 --> 00:08:23.962 We can see the name backwards, like txt there 189 00:08:23.962 --> 00:08:26.903 and mode equals w in the printed representation 190 00:08:26.903 --> 00:08:29.064 of the file down here in the Run window. 191 00:08:29.064 --> 00:08:31.212 Now if the print function changes in the future, 192 00:08:31.212 --> 00:08:33.364 to have additional keyword arguments 193 00:08:33.364 --> 00:08:35.875 our code will still work fine. 194 00:08:35.875 --> 00:08:37.333 The user can specify them 195 00:08:37.333 --> 00:08:39.645 when calling our print_backwards function, 196 00:08:39.645 --> 00:08:42.573 and we just pass them on to the builtin print. 197 00:08:42.573 --> 00:08:45.247 That means that we can handle functions in classes, 198 00:08:45.247 --> 00:08:46.738 that take keyword arguments, 199 00:08:46.738 --> 00:08:48.574 that we don't have to know or care about 200 00:08:48.574 --> 00:08:51.378 and that obviously makes life a lot easier. 201 00:08:51.378 --> 00:08:53.588 However with that said, there's a slight problem 202 00:08:53.588 --> 00:08:55.407 with this code and it's easy to fix 203 00:08:55.407 --> 00:08:57.708 and that's gonna be your next challenge. 204 00:08:57.708 --> 00:08:59.885 But I'll end the video here. 205 00:08:59.885 --> 00:09:01.247 In the next video, we'll have a look 206 00:09:01.247 --> 00:09:02.713 and see what the problem is first 207 00:09:02.713 --> 00:09:04.060 and then we'll get you to look at it, 208 00:09:04.060 --> 00:09:06.021 by way of a challenge to solve that problem. 209 00:09:06.021 --> 00:09:08.854 So I'll see you in the next video.