1 00:00:00,480 --> 00:00:03,330 In the last lesson we saw how the asterix operator 2 00:00:03,330 --> 00:00:07,320 could be used to provide any number of positional arguments to a function 3 00:00:07,680 --> 00:00:11,370 because it collected them into a tuple. In this lesson, 4 00:00:11,430 --> 00:00:14,130 we'll take a look at the double asterix operator, 5 00:00:14,430 --> 00:00:18,750 and this is going to allow us to work with an arbitrary number of keyword 6 00:00:18,750 --> 00:00:20,940 arguments. Let's see this in action. 7 00:00:21,600 --> 00:00:24,360 So let's say I create another function called calculate, 8 00:00:24,720 --> 00:00:29,160 and this time I'm going to add two asteriks. And in this case, 9 00:00:29,220 --> 00:00:34,220 I'm going to call my argument **kwargs or keyword arguments. 10 00:00:34,770 --> 00:00:39,770 What we've done now is we've added two asterisks signs in front of this parameter 11 00:00:39,900 --> 00:00:40,733 name, 12 00:00:41,160 --> 00:00:45,630 and we've now created unlimited keyword arguments. 13 00:00:46,080 --> 00:00:51,080 What this allows me to do is I could basically now call this calculate function, 14 00:00:52,380 --> 00:00:57,090 I could pass in a keyword argument, for example, 15 00:00:57,210 --> 00:01:00,210 add, and let's give it a value, maybe three, 16 00:01:00,510 --> 00:01:04,739 and then let's add another keyword argument which I'll call multiply, 17 00:01:05,069 --> 00:01:08,910 set that to equal five. And effectively 18 00:01:08,940 --> 00:01:13,140 what this has been turned into is these **kwargs, 19 00:01:13,500 --> 00:01:18,210 which is basically a dictionary. So if I print these **kwargs, 20 00:01:18,810 --> 00:01:23,040 you can see what gets printed is basically a bog-standard dictionary. 21 00:01:23,490 --> 00:01:26,790 And in fact, if we do that type check thing again, so type, 22 00:01:28,620 --> 00:01:30,900 you can see it is in fact, a dictionary. 23 00:01:31,920 --> 00:01:36,810 This dictionary basically represents each of the keyword arguments and their 24 00:01:36,810 --> 00:01:37,643 values. 25 00:01:37,950 --> 00:01:42,570 So add is now a key and three is now it's value, multiply's 26 00:01:42,570 --> 00:01:45,660 the second key and five is its value. 27 00:01:46,140 --> 00:01:50,760 What I can do here is I could do the standard way of looping through dictionary. 28 00:01:50,760 --> 00:01:55,760 So I could say for key, value in **kwargs .items, 29 00:01:57,960 --> 00:02:02,160 and then I can get access to each of the keys and their values as I loop through 30 00:02:02,160 --> 00:02:04,800 the dictionary like this. 31 00:02:04,920 --> 00:02:08,910 So add three multiplied by five. Alternatively, 32 00:02:08,970 --> 00:02:11,700 I can simply use the names of the keys. 33 00:02:12,120 --> 00:02:17,120 So I could just simply print my **kwargs and then use the square brackets and then 34 00:02:18,270 --> 00:02:22,200 provide the name of the key, so add for example. 35 00:02:22,950 --> 00:02:27,060 And that will give me the value which is three as you can see here. 36 00:02:27,930 --> 00:02:28,260 Now, 37 00:02:28,260 --> 00:02:33,260 what this allows me to do is it basically lets me look through all of the inputs 38 00:02:34,920 --> 00:02:39,060 and find the ones that I want and use them to do something. 39 00:02:39,540 --> 00:02:44,100 So for example, in this case, it's a calculate function, right? 40 00:02:44,490 --> 00:02:48,420 So we could let's say start off with a normal positional argument, 41 00:02:48,450 --> 00:02:53,370 so let's call it n and let's pass in that n at the very beginning. 42 00:02:53,670 --> 00:02:58,500 So let's say we start out with the number 2, n is now equal to 2, 43 00:02:58,900 --> 00:03:03,700 and then the **kwargs is a dictionary of the remainder arguments. 44 00:03:05,290 --> 00:03:08,020 Let's say that I wanted to do some calculations. 45 00:03:08,050 --> 00:03:13,050 I wanted to say n+= kwargs, 46 00:03:13,870 --> 00:03:18,340 and I'm going to get hold of the value under add. 47 00:03:19,030 --> 00:03:22,960 And then I'm going to say, n*= the kwargs, 48 00:03:23,380 --> 00:03:26,290 and I'm going to get hold of value of multiply. 49 00:03:26,950 --> 00:03:30,250 So now when I go ahead and print 50 00:03:30,310 --> 00:03:35,310 my n, you can see that what happens is it takes the first value 2 as equal to n, 51 00:03:39,850 --> 00:03:44,380 and then n, this 2, is going to be added to the number I wanted to add 52 00:03:44,410 --> 00:03:46,660 which is 3. So 2 + 3 is 5, 53 00:03:47,140 --> 00:03:52,140 and then it multiplied that 5 by whatever it is I had stored in multiply. 54 00:03:52,660 --> 00:03:55,120 So 5 plus 5, and we get 25. 55 00:03:55,810 --> 00:04:00,460 This gives us a more flexible way of working with these arguments. 56 00:04:00,910 --> 00:04:05,500 And it gives us a way to name the values that we're passing in to this function. 57 00:04:06,880 --> 00:04:11,110 Now, coming back to what they've done in the Tkinter module, 58 00:04:11,650 --> 00:04:16,649 basically this Tkinter module is actually ported from another technology called 59 00:04:17,560 --> 00:04:18,392 TK. 60 00:04:18,940 --> 00:04:23,320 And TK actually has a very different syntax from Python. 61 00:04:23,950 --> 00:04:28,900 In order for it to work, they basically took all of the Tk commands, 62 00:04:28,930 --> 00:04:32,470 like creating a label or packing some sort of item, 63 00:04:32,920 --> 00:04:37,920 and took all of the options and turn them into these **kwargs or optional keyword 64 00:04:40,180 --> 00:04:41,013 arguments. 65 00:04:41,380 --> 00:04:46,000 And that is why when we create a new label from the Tkinter module 66 00:04:46,030 --> 00:04:48,310 or when we call the pack method, 67 00:04:48,520 --> 00:04:53,290 you can see that it doesn't actually come up with any properties that we can 68 00:04:53,290 --> 00:04:57,850 modify other than this **kw, 69 00:04:58,120 --> 00:05:00,580 which is the same as our **kwargs. 70 00:05:01,390 --> 00:05:04,390 So we could actually create a class like that as well, 71 00:05:04,660 --> 00:05:07,180 because this is done at initialization, right? 72 00:05:07,180 --> 00:05:09,640 This is done when they're creating that label class. 73 00:05:10,420 --> 00:05:13,810 Let's say that we create a class like this which I'll car, 74 00:05:14,410 --> 00:05:16,270 and in the init, 75 00:05:16,780 --> 00:05:21,430 what I'll include in addition to self is ** 76 00:05:21,670 --> 00:05:25,030 kw, or **kwargs, or however you want to spell it. 77 00:05:25,840 --> 00:05:30,840 This kw are going to be all of the optional arguments that I'll pass in 78 00:05:31,270 --> 00:05:35,950 when I'm initializing a new object from this class. I can say, 79 00:05:35,950 --> 00:05:38,770 for example, self. 80 00:05:38,830 --> 00:05:42,370 make of the car equals kw. 81 00:05:43,270 --> 00:05:47,230 And then from kw, I'm going to get the make. 82 00:05:48,010 --> 00:05:49,810 And then I'm going to have self.model 83 00:05:49,810 --> 00:05:53,980 which is going to be equal to kw and then model. And of course, 84 00:05:53,980 --> 00:05:57,830 all of the spelling matters so make sure you don't make any typos. 85 00:05:58,280 --> 00:06:00,260 And then I decide to create my car 86 00:06:00,290 --> 00:06:04,490 which is going to be the object created from this class. Now notice how 87 00:06:04,490 --> 00:06:06,440 when I open up the parentheses here, 88 00:06:06,740 --> 00:06:10,850 you don't actually see any of the properties like make and model show up 89 00:06:10,880 --> 00:06:14,480 when I'm initializing. All you see is ** 90 00:06:14,510 --> 00:06:18,380 kw, just in the same way as you see it here, 91 00:06:19,850 --> 00:06:21,680 **kw. 92 00:06:22,640 --> 00:06:26,750 And that of course refers to our optional keyword arguments. 93 00:06:27,320 --> 00:06:31,610 Let's add some values. Let's set the make to a Nissan, 94 00:06:32,150 --> 00:06:37,150 and lets set the model to a-- let's set it to a GT-R. And now I can use my object 95 00:06:40,820 --> 00:06:44,930 just as I would any other object. I can say my_car.model. 96 00:06:45,290 --> 00:06:49,580 And when I hit run, you can see I've got GT-R being printed here. 97 00:06:50,690 --> 00:06:54,740 And if I decided to print make, you can see 98 00:06:54,740 --> 00:06:55,970 it gets hold off the make. 99 00:06:56,480 --> 00:07:00,830 Now, what if I didn't actually specify one of these arguments. 100 00:07:01,430 --> 00:07:05,390 Notice how it's now actually going to crash. 101 00:07:06,020 --> 00:07:08,570 It tells me that keyError model. 102 00:07:08,750 --> 00:07:13,750 So when it was initializing this car object, it fell on this line. And it 103 00:07:15,800 --> 00:07:20,800 couldn't get hold of a value called model from this kw argument dictionary. 104 00:07:23,060 --> 00:07:24,650 In fact, with dictionaries, 105 00:07:25,040 --> 00:07:28,370 we can get hold of the values through the square bracket method, 106 00:07:28,640 --> 00:07:33,640 but we can also use a function called get. And we use get in a very similar way 107 00:07:35,030 --> 00:07:37,220 to the way that we use the square brackets. 108 00:07:37,250 --> 00:07:41,540 We just pass in the name of the key and we want to get hold of the value. 109 00:07:42,140 --> 00:07:47,140 But the benefit of get is that if this key doesn't exist in the dictionary, 110 00:07:50,510 --> 00:07:54,650 then it will just return none and it won't give us an error. 111 00:07:55,820 --> 00:08:00,080 So now if I run this code again, you can see that everything works, 112 00:08:00,320 --> 00:08:03,890 but my car.model is now equal to none. 113 00:08:04,580 --> 00:08:09,580 So this is how we can actually create a class with lots of optional keyword 114 00:08:10,340 --> 00:08:11,173 arguments. 115 00:08:12,110 --> 00:08:17,110 So we could have a self.color or self.seats. 116 00:08:21,050 --> 00:08:25,580 And depending on what it is we want to initialize this car object to, 117 00:08:25,910 --> 00:08:30,910 then we can simply go ahead and add whatever it is we want to set as the make 118 00:08:31,820 --> 00:08:35,750 and the model or the color and the seats. And in the same way 119 00:08:35,780 --> 00:08:38,059 that way using this label class, 120 00:08:38,390 --> 00:08:41,150 we can set the text or we can set the font. 121 00:08:41,270 --> 00:08:46,270 We can set all of the options or we can leave them as the default values. That 122 00:08:48,230 --> 00:08:52,610 should help you understand how this code works a little bit better. 123 00:08:53,180 --> 00:08:56,580 And the reason why it works like this is, as I say, 124 00:08:56,580 --> 00:09:01,580 mostly because this module was converted from another language and this just 125 00:09:01,950 --> 00:09:06,950 happened to be the most efficient way for them to do this. Now with other more 126 00:09:07,380 --> 00:09:11,280 Pythonic modules or things that have been created in Python 127 00:09:11,610 --> 00:09:16,260 like the turtle module, then you'll see more bog-standard kind of code 128 00:09:16,320 --> 00:09:19,740 like what we've been working with. So when we initialize a new turtle, 129 00:09:19,950 --> 00:09:22,530 you can see that it has a default shape, 130 00:09:22,620 --> 00:09:25,230 it has a visible boolean, 131 00:09:25,290 --> 00:09:29,190 and we can set all of those properties that we can see in this prompt. 132 00:09:30,510 --> 00:09:31,860 Now in the next lesson, 133 00:09:31,890 --> 00:09:36,210 I want to dive deeper into the TKinter documentation 134 00:09:36,570 --> 00:09:40,230 and I want to show you how we can create other components, not just the label, 135 00:09:40,470 --> 00:09:42,990 but things like buttons and text inputs 136 00:09:43,280 --> 00:09:46,790 and a whole range of things that will bring our GUI program to life. 137 00:09:47,210 --> 00:09:50,120 So for all of that and more, I'll see you in the next lesson.