1 00:00:00,000 --> 00:00:03,304 [MUSIC PLAYING] 2 00:00:03,304 --> 00:00:05,192 3 00:00:05,192 --> 00:00:09,150 CARTER ZENKE: Well, hello one and all, and welcome to our short on instance 4 00:00:09,150 --> 00:00:10,120 methods. 5 00:00:10,120 --> 00:00:15,420 Now, we've seen in prior shorts on defining classes and instance variables 6 00:00:15,420 --> 00:00:19,050 ways to define some template for some object and ways 7 00:00:19,050 --> 00:00:24,540 to instantiate individual instances of those templates to refer to in code 8 00:00:24,540 --> 00:00:28,590 and access their various instance variables, or traits, of each 9 00:00:28,590 --> 00:00:31,270 of those individual, in this case packages. 10 00:00:31,270 --> 00:00:34,110 So we have here again a class called package 11 00:00:34,110 --> 00:00:38,490 that encapsulates some information about packages in general. 12 00:00:38,490 --> 00:00:41,100 We say that every package we'll create will 13 00:00:41,100 --> 00:00:47,620 have a number, like an ID, a sender, a recipient, and a weight to it. 14 00:00:47,620 --> 00:00:51,420 And we then define here the various instance variables whenever 15 00:00:51,420 --> 00:00:55,050 we create a new instance of this class. 16 00:00:55,050 --> 00:01:00,160 Down below, on lines 11 and 12, we actually create these instances. 17 00:01:00,160 --> 00:01:03,820 We have here on line 11 a package whose number 18 00:01:03,820 --> 00:01:07,120 is 1, whose sender is Alice, whose recipient is 19 00:01:07,120 --> 00:01:10,010 Bob, and whose weight is 10. 20 00:01:10,010 --> 00:01:12,790 And then, finally, down below on line 14, 21 00:01:12,790 --> 00:01:15,820 we have some code here that actually accesses the instance 22 00:01:15,820 --> 00:01:21,410 variables to print out in a more pretty format the package information itself. 23 00:01:21,410 --> 00:01:25,430 So let's try running this and see the output down below once more. 24 00:01:25,430 --> 00:01:30,160 I'll run Python of packages.py, and we'll see, thanks to the code 25 00:01:30,160 --> 00:01:34,840 that we all have here, we're able to print information on these packages 26 00:01:34,840 --> 00:01:39,820 while still encapsulating combine the information in a more organized way. 27 00:01:39,820 --> 00:01:45,280 Now, it turns out that I can use classes to not just encapsulate or combine 28 00:01:45,280 --> 00:01:49,690 pieces of information but to also encapsulate functionality 29 00:01:49,690 --> 00:01:53,420 that I want to be common across all individual packages. 30 00:01:53,420 --> 00:01:56,240 And I can do so by defining, in this case, 31 00:01:56,240 --> 00:01:59,680 what I might call an instance method, a method that 32 00:01:59,680 --> 00:02:03,820 can be run on any instance of this particular class. 33 00:02:03,820 --> 00:02:07,920 Now, when I say method here, I'm really referring to a particular kind 34 00:02:07,920 --> 00:02:11,380 of function that is part of a class. 35 00:02:11,380 --> 00:02:15,070 And I want to show you one that you might find handy, 36 00:02:15,070 --> 00:02:19,330 one called dunder S-T-R, dunder STR. 37 00:02:19,330 --> 00:02:24,870 So similar to dunder init, dunder STR is a special instance method 38 00:02:24,870 --> 00:02:29,550 that can be called if I were to print some package. 39 00:02:29,550 --> 00:02:34,230 Now, down below here, on line 15, this is a long line of code. 40 00:02:34,230 --> 00:02:39,270 But wouldn't it be nice, let's say, if I could simply print a package like this-- 41 00:02:39,270 --> 00:02:44,700 print package-- and get, let's say, the same format I have down below? 42 00:02:44,700 --> 00:02:46,690 Right now, this will not be the case. 43 00:02:46,690 --> 00:02:52,240 If I run python of package.py, I'll see this, which is not very pretty at all. 44 00:02:52,240 --> 00:02:58,320 But I could add an instance method called dunder STR to actually improve 45 00:02:58,320 --> 00:03:03,330 the output of, in this case, what I see when I call print on any given 46 00:03:03,330 --> 00:03:06,250 instance of my package class. 47 00:03:06,250 --> 00:03:07,870 So let's go back up here. 48 00:03:07,870 --> 00:03:12,850 And to define some new instance method, I can simply drop down a line 49 00:03:12,850 --> 00:03:16,730 and define some new function that's part of my class. 50 00:03:16,730 --> 00:03:21,010 And because this one is a special method defined as some special functionality 51 00:03:21,010 --> 00:03:25,940 by Python itself, I'll use these double underscores and then STR. 52 00:03:25,940 --> 00:03:30,130 In fact, the double underscores, pronounced as dunder, 53 00:03:30,130 --> 00:03:32,950 they tend to refer to these special methods 54 00:03:32,950 --> 00:03:35,810 that Python attaches some special meaning to. 55 00:03:35,810 --> 00:03:38,830 In this case, dunder STR is actually called 56 00:03:38,830 --> 00:03:41,590 every time I print-- every time I call print 57 00:03:41,590 --> 00:03:45,110 on an instance of my individual package. 58 00:03:45,110 --> 00:03:50,680 So by convention, dunder STR takes as input, in this case-- 59 00:03:50,680 --> 00:03:55,970 in this case, the instance of the class itself that we refer to as self. 60 00:03:55,970 --> 00:04:00,970 And within dunder STR, I can return some string 61 00:04:00,970 --> 00:04:06,220 that will be printed every time I call print on an instance of the package. 62 00:04:06,220 --> 00:04:10,360 So just as a test here, why don't I say-- 63 00:04:10,360 --> 00:04:12,910 why don't I say "This is a package." 64 00:04:12,910 --> 00:04:14,150 "This is a package." 65 00:04:14,150 --> 00:04:21,310 So every time I call print on a package, hopefully I'll see "This is a package." 66 00:04:21,310 --> 00:04:22,930 I'll go ahead and run-- 67 00:04:22,930 --> 00:04:27,250 I'll go ahead and run Python of packages.py. 68 00:04:27,250 --> 00:04:31,420 And for both of those within my list here, this package and this package, 69 00:04:31,420 --> 00:04:37,120 we'll see "This is a package," which is helpful but only a little bit. 70 00:04:37,120 --> 00:04:41,350 Ideally, I'd show some information on the actual instance 71 00:04:41,350 --> 00:04:43,220 of the package I'm talking about. 72 00:04:43,220 --> 00:04:48,790 So to do so, I can again access these instance variables and return, 73 00:04:48,790 --> 00:04:50,830 let's say, something like an f string that's 74 00:04:50,830 --> 00:04:52,810 in the same format we had down below. 75 00:04:52,810 --> 00:04:58,075 I could say package again and then self.number, colon, maybe 76 00:04:58,075 --> 00:05:10,390 self.sender to self.recipient, and then a comma, self.weight kg, just like this. 77 00:05:10,390 --> 00:05:14,780 So this is the same f string we had in that for loop. 78 00:05:14,780 --> 00:05:18,310 But now I've encapsulated that same f string 79 00:05:18,310 --> 00:05:24,650 inside of my package class within this instance method called dunder STR. 80 00:05:24,650 --> 00:05:28,660 Now, ideally, when I run Python of packages.py, 81 00:05:28,660 --> 00:05:31,660 we'll see some more information on this package. 82 00:05:31,660 --> 00:05:36,060 But much more simply now, we can simply call print package. 83 00:05:36,060 --> 00:05:41,050 I'll run this, and we'll see that same information now part of some instance 84 00:05:41,050 --> 00:05:43,310 method called dunder STR. 85 00:05:43,310 --> 00:05:44,920 So pretty handy here. 86 00:05:44,920 --> 00:05:48,680 Now, what else could we actually use instance methods for? 87 00:05:48,680 --> 00:05:51,520 Well, we want to maybe attach functionality 88 00:05:51,520 --> 00:05:56,290 that seems pretty core to the idea of being a package. 89 00:05:56,290 --> 00:05:58,600 Maybe one thing we want packages to be able to do 90 00:05:58,600 --> 00:06:01,600 is calculate the cost of shipping them. 91 00:06:01,600 --> 00:06:05,600 So I could imagine here defining another instance method, maybe 92 00:06:05,600 --> 00:06:09,770 one called calculate cost, that allows a package to figure out 93 00:06:09,770 --> 00:06:12,190 how much it costs itself to ship. 94 00:06:12,190 --> 00:06:17,930 So I could define here maybe a new method called calculate_cost. 95 00:06:17,930 --> 00:06:21,110 And these instance methods, by default, again, 96 00:06:21,110 --> 00:06:24,950 take as input as the first argument the instance itself 97 00:06:24,950 --> 00:06:29,480 that we refer to as this variable, this argument called self. 98 00:06:29,480 --> 00:06:35,270 Now, as another input to calculate cost, maybe the cost changes. 99 00:06:35,270 --> 00:06:39,620 It may be a cost per kilogram that I could specify as input 100 00:06:39,620 --> 00:06:42,980 to this particular method here. 101 00:06:42,980 --> 00:06:44,000 I'll type a colon. 102 00:06:44,000 --> 00:06:46,820 And within this particular function body I 103 00:06:46,820 --> 00:06:52,220 can then define this instance method called calculate_cost. 104 00:06:52,220 --> 00:06:56,250 Let's first see how to use this instance method though. 105 00:06:56,250 --> 00:07:00,392 Maybe instead of going down here and just printing the package, 106 00:07:00,392 --> 00:07:02,100 I could do something a little more fancy. 107 00:07:02,100 --> 00:07:07,540 I could say, why don't we print the package itself as part of this f string 108 00:07:07,540 --> 00:07:10,300 but then also say that it costs-- 109 00:07:10,300 --> 00:07:12,820 it costs some amount? 110 00:07:12,820 --> 00:07:16,120 Now that I have this function called calculate_cost 111 00:07:16,120 --> 00:07:20,420 that is yet unimplemented, I could use it as follows. 112 00:07:20,420 --> 00:07:24,850 For each instance in this case that we're calling package in this for loop, 113 00:07:24,850 --> 00:07:28,840 I could call calculate_cost by typing a dot and then 114 00:07:28,840 --> 00:07:33,040 the function the actual method name, so calculate_cost. 115 00:07:33,040 --> 00:07:37,150 And now as input to calculate_cost, I could actually 116 00:07:37,150 --> 00:07:41,530 type in the input I'm expecting, cost_per_kg. 117 00:07:41,530 --> 00:07:43,840 So I'll say cost_per_kg. 118 00:07:43,840 --> 00:07:48,190 And why don't we say it's about 2 US dollars per kilogram 119 00:07:48,190 --> 00:07:51,130 to ship some given package? 120 00:07:51,130 --> 00:07:54,640 So this is how I want to use calculate_cost, but now 121 00:07:54,640 --> 00:07:57,220 let's implement it up on line 11. 122 00:07:57,220 --> 00:08:01,647 Well, I want to make sure to return here the total cost of the package. 123 00:08:01,647 --> 00:08:03,230 I actually know the cost per kilogram. 124 00:08:03,230 --> 00:08:06,140 So to do that, I think I just need some multiplication. 125 00:08:06,140 --> 00:08:09,370 I could maybe find the weight in kilograms 126 00:08:09,370 --> 00:08:12,680 and multiply it by the cost per kilogram. 127 00:08:12,680 --> 00:08:19,450 So I could say maybe self.weight, again accessing some instance variable, 128 00:08:19,450 --> 00:08:23,380 and multiply that by the cost per kilogram. 129 00:08:23,380 --> 00:08:25,540 And we'll make the assumption here the user 130 00:08:25,540 --> 00:08:29,200 knows that weight should be in kilograms. 131 00:08:29,200 --> 00:08:32,770 So we'll go ahead and say this is calculate_cost. 132 00:08:32,770 --> 00:08:37,159 It takes the weight in kilograms, multiplies it by the cost per kilogram, 133 00:08:37,159 --> 00:08:41,000 and that is the cost of shipping this particular package. 134 00:08:41,000 --> 00:08:42,830 So let's try it down below. 135 00:08:42,830 --> 00:08:47,110 Why don't I go ahead and run Python of packages.pi? 136 00:08:47,110 --> 00:08:52,630 And now we'll see package 1, Alice to Bob, 10 kg costs 20, 137 00:08:52,630 --> 00:08:55,252 and package 2 costs 10. 138 00:08:55,252 --> 00:08:56,960 Could probably improve this a little bit. 139 00:08:56,960 --> 00:09:00,370 We could maybe add a dollar sign here to say this is in US dollars. 140 00:09:00,370 --> 00:09:03,220 We'll run packages.py again, and now we'll 141 00:09:03,220 --> 00:09:06,150 see some pretty good formatting here. 142 00:09:06,150 --> 00:09:10,830 So this was our brief foray into instance methods. 143 00:09:10,830 --> 00:09:13,070 There are some special ones like dunder STR 144 00:09:13,070 --> 00:09:18,590 that allows to say how a instance should be printed, as we saw down below. 145 00:09:18,590 --> 00:09:22,770 We can also add some functionality, encapsulate functionality, 146 00:09:22,770 --> 00:09:27,570 in this case like one to calculate the cost of shipping some given package. 147 00:09:27,570 --> 00:09:30,210 This then was our short on instance methods. 148 00:09:30,210 --> 00:09:32,980 And we'll see you next time. 149 00:09:32,980 --> 00:09:35,000