1 00:00:00,790 --> 00:00:03,190 The following content is provided under a Creative 2 00:00:03,190 --> 00:00:04,730 Commons license. 3 00:00:04,730 --> 00:00:07,030 Your support will help MIT OpenCourseWare 4 00:00:07,030 --> 00:00:11,390 continue to offer high-quality educational resources for free. 5 00:00:11,390 --> 00:00:13,990 To make a donation or view additional materials 6 00:00:13,990 --> 00:00:17,880 from hundreds of MIT courses, visit MIT OpenCourseWare 7 00:00:17,880 --> 00:00:18,840 at ocw.mit.edu. 8 00:00:31,789 --> 00:00:33,830 ANA BELL: All right, everyone, let's get started. 9 00:00:37,670 --> 00:00:40,100 So today is going to be the second lecture 10 00:00:40,100 --> 00:00:41,600 on object-oriented programming. 11 00:00:41,600 --> 00:00:44,930 So just a quick recap of last time-- on Monday, 12 00:00:44,930 --> 00:00:47,907 we saw-- we were introduced to this idea 13 00:00:47,907 --> 00:00:49,490 of object-oriented programming, and we 14 00:00:49,490 --> 00:00:52,230 saw these things called abstract data types. 15 00:00:52,230 --> 00:00:54,350 And these abstract data types we implemented 16 00:00:54,350 --> 00:00:57,170 through Python classes. 17 00:00:57,170 --> 00:01:01,400 And they allowed us to create our own data types 18 00:01:01,400 --> 00:01:06,001 that sort of abstracted a general object of our choosing, 19 00:01:06,001 --> 00:01:06,500 right? 20 00:01:06,500 --> 00:01:09,099 So we've used lists before, for example. 21 00:01:09,099 --> 00:01:10,640 But with abstract data types, we were 22 00:01:10,640 --> 00:01:15,110 able to create objects that were of our own types. 23 00:01:15,110 --> 00:01:16,430 We saw the coordinate example. 24 00:01:16,430 --> 00:01:17,804 And then at the end of the class, 25 00:01:17,804 --> 00:01:19,104 we saw the fraction example. 26 00:01:19,104 --> 00:01:21,020 So today we're going to talk a little bit more 27 00:01:21,020 --> 00:01:23,060 about object-oriented programming and classes. 28 00:01:23,060 --> 00:01:25,730 We're going to see a few more examples. 29 00:01:25,730 --> 00:01:32,000 And we're going to talk about a few other nuances of classes, 30 00:01:32,000 --> 00:01:35,217 talk about information hiding and class variables. 31 00:01:35,217 --> 00:01:36,800 And in the second half of the lecture, 32 00:01:36,800 --> 00:01:39,480 we're going to talk about the idea of inheritance. 33 00:01:39,480 --> 00:01:42,710 So we're going to use object-oriented programming 34 00:01:42,710 --> 00:01:44,877 to simulate how real life works. 35 00:01:44,877 --> 00:01:46,460 So in real life, you have inheritance. 36 00:01:46,460 --> 00:01:49,010 And in object-oriented programming, 37 00:01:49,010 --> 00:01:52,480 you can also simulate that. 38 00:01:52,480 --> 00:01:54,219 OK, so the first few slides are going 39 00:01:54,219 --> 00:01:56,760 to be a little bit of recap just to make sure that everyone's 40 00:01:56,760 --> 00:01:58,920 on the same page before I introduce 41 00:01:58,920 --> 00:02:02,130 a couple of new concepts related to classes. 42 00:02:02,130 --> 00:02:05,010 So recall that when-- in the last lecture, 43 00:02:05,010 --> 00:02:07,240 we talked about writing code from two 44 00:02:07,240 --> 00:02:08,490 different perspectives, right? 45 00:02:08,490 --> 00:02:12,450 The first was from someone who wanted to implement a class. 46 00:02:12,450 --> 00:02:17,810 So implementing the class meant defining your own object type. 47 00:02:17,810 --> 00:02:21,210 So you defined the object type when you defined the class. 48 00:02:21,210 --> 00:02:24,680 And then you decided what data attributes you wanted 49 00:02:24,680 --> 00:02:26,510 to define in your object. 50 00:02:26,510 --> 00:02:29,180 So what data makes up the object? 51 00:02:29,180 --> 00:02:32,740 What is the object, OK? 52 00:02:32,740 --> 00:02:34,500 In addition to data attributes, we also 53 00:02:34,500 --> 00:02:37,800 saw these things called methods. 54 00:02:37,800 --> 00:02:40,110 And methods were ways to tell someone 55 00:02:40,110 --> 00:02:41,827 how to use your data type. 56 00:02:41,827 --> 00:02:44,160 So what are ways that someone can interact with the data 57 00:02:44,160 --> 00:02:45,489 type, OK? 58 00:02:45,489 --> 00:02:47,280 So that's from the point of view of someone 59 00:02:47,280 --> 00:02:49,650 who wants to write their own object type. 60 00:02:49,650 --> 00:02:53,470 So you're implementing a class. 61 00:02:53,470 --> 00:02:56,536 And the other perspective was to write code 62 00:02:56,536 --> 00:02:57,910 from the point of view of someone 63 00:02:57,910 --> 00:03:01,450 who wanted to use a class that was already written, OK? 64 00:03:01,450 --> 00:03:04,690 So this involved creating instances of objects. 65 00:03:04,690 --> 00:03:07,980 So you're using the object type. 66 00:03:07,980 --> 00:03:09,660 Once you created instances of objects, 67 00:03:09,660 --> 00:03:11,320 you were able to do operations on them. 68 00:03:11,320 --> 00:03:13,560 So you were able to see what methods whoever 69 00:03:13,560 --> 00:03:15,420 implemented the class added. 70 00:03:15,420 --> 00:03:17,160 And then, you can use those methods 71 00:03:17,160 --> 00:03:24,450 in order to do operations with your instances. 72 00:03:24,450 --> 00:03:27,080 So just looking at the coordinate example we 73 00:03:27,080 --> 00:03:29,060 saw last time, a little bit more in detail 74 00:03:29,060 --> 00:03:32,590 about what that meant-- so we had a class 75 00:03:32,590 --> 00:03:36,800 definition of an object type, which included deciding 76 00:03:36,800 --> 00:03:38,950 what the class name was. 77 00:03:38,950 --> 00:03:40,990 And the class name basically told 78 00:03:40,990 --> 00:03:43,780 Python what type of an object this was, OK? 79 00:03:43,780 --> 00:03:45,610 In this case, we decided we wanted 80 00:03:45,610 --> 00:03:49,060 to name a coordinate-- we wanted to create a Coordinate object. 81 00:03:49,060 --> 00:03:51,460 And the type of this object was therefore 82 00:03:51,460 --> 00:03:53,920 going to be a coordinate. 83 00:03:53,920 --> 00:03:57,220 We defined the class in the sort of general way, OK? 84 00:03:57,220 --> 00:03:59,890 So we needed a way to be able to access data 85 00:03:59,890 --> 00:04:02,950 attributes of any instance. 86 00:04:02,950 --> 00:04:06,565 So we use this self variable, OK? 87 00:04:06,565 --> 00:04:09,910 And the self variable we used to refer 88 00:04:09,910 --> 00:04:15,180 to any instance-- to the data attributes of any instance 89 00:04:15,180 --> 00:04:16,769 in a general way without actually 90 00:04:16,769 --> 00:04:20,070 having a particular instance in mind, OK? 91 00:04:20,070 --> 00:04:21,959 So whenever we access data attributes, 92 00:04:21,959 --> 00:04:26,230 we would say something like self dot to access a data attribute. 93 00:04:26,230 --> 00:04:29,160 You'd access the attribute directly with self.x. 94 00:04:29,160 --> 00:04:30,690 Or if you wanted to access a method, 95 00:04:30,690 --> 00:04:33,149 you would say self, dot, and then the method name-- 96 00:04:33,149 --> 00:04:34,065 for example, distance. 97 00:04:37,350 --> 00:04:39,870 And really, the bottom line of the class definition 98 00:04:39,870 --> 00:04:42,912 is that your class defines all of the data-- so data 99 00:04:42,912 --> 00:04:44,370 attributes-- and all of the methods 100 00:04:44,370 --> 00:04:47,190 that are going to be common across all of the instances. 101 00:04:47,190 --> 00:04:52,410 So any instance that you create of a particular object type, 102 00:04:52,410 --> 00:04:58,490 that instance is going to have this exact same structure, OK? 103 00:04:58,490 --> 00:05:02,570 The difference is that every instance's values 104 00:05:02,570 --> 00:05:05,270 are going to be different. 105 00:05:05,270 --> 00:05:08,200 So when you're creating instances of classes, 106 00:05:08,200 --> 00:05:11,770 you can create more than one instance of the same class. 107 00:05:11,770 --> 00:05:14,470 So we can create a Coordinate object here 108 00:05:14,470 --> 00:05:17,650 using this syntax right here. 109 00:05:17,650 --> 00:05:22,030 So you say the type, and then, whatever values it takes in. 110 00:05:22,030 --> 00:05:24,380 And you can create more than one Coordinate object. 111 00:05:27,570 --> 00:05:30,150 Each Coordinate object is going to have different data 112 00:05:30,150 --> 00:05:32,430 attributes. 113 00:05:32,430 --> 00:05:34,610 Sorry, it's going to have different data attribute 114 00:05:34,610 --> 00:05:36,740 values, OK? 115 00:05:36,740 --> 00:05:39,650 Every Coordinate object is going to have an x value and a y 116 00:05:39,650 --> 00:05:41,530 value. 117 00:05:41,530 --> 00:05:45,280 But the x and y values among different instances 118 00:05:45,280 --> 00:05:47,680 are going to vary, OK? 119 00:05:47,680 --> 00:05:50,240 So that's the difference between defining a class 120 00:05:50,240 --> 00:05:52,240 and looking at a particular instance of a class. 121 00:05:52,240 --> 00:05:54,370 So instances have the structure of the class. 122 00:05:54,370 --> 00:05:56,950 So for a coordinate, all instances 123 00:05:56,950 --> 00:05:59,740 have an x value and a y value. 124 00:05:59,740 --> 00:06:01,840 But the actual values are going to vary 125 00:06:01,840 --> 00:06:04,340 between the different instances. 126 00:06:04,340 --> 00:06:06,580 OK, so ultimately, why do we want 127 00:06:06,580 --> 00:06:08,170 to use object-oriented programming? 128 00:06:08,170 --> 00:06:12,440 So, so far, the examples that we've seen 129 00:06:12,440 --> 00:06:16,520 were numerical, right-- a coordinate, a fraction. 130 00:06:16,520 --> 00:06:19,640 But using object-oriented programming, 131 00:06:19,640 --> 00:06:24,730 you can create objects that mimic real life. 132 00:06:24,730 --> 00:06:29,650 So if I wanted to create objects of-- an object that 133 00:06:29,650 --> 00:06:32,230 defined a cat and an object that defined a rabbit, 134 00:06:32,230 --> 00:06:34,930 I could do that with object-oriented programming. 135 00:06:34,930 --> 00:06:38,140 I would just have to decide, as a programmer, what 136 00:06:38,140 --> 00:06:40,350 data and what methods I'd want to assign 137 00:06:40,350 --> 00:06:45,210 to these groups of objects, OK? 138 00:06:45,210 --> 00:06:48,840 So using object-oriented programming, each one of these 139 00:06:48,840 --> 00:06:51,270 is considered a different object. 140 00:06:51,270 --> 00:06:53,370 And as a different object, I can decide 141 00:06:53,370 --> 00:06:56,280 that a cat is going to have a name, an age, and maybe 142 00:06:56,280 --> 00:06:57,950 a color associated with it. 143 00:07:00,872 --> 00:07:02,330 And these three here, on the right, 144 00:07:02,330 --> 00:07:04,587 each one of these rabbits is also an object. 145 00:07:04,587 --> 00:07:06,170 And I'm going to decide that I'm going 146 00:07:06,170 --> 00:07:11,710 to represent a rabbit by just an age and a color, OK? 147 00:07:11,710 --> 00:07:15,990 And with object-oriented programming, 148 00:07:15,990 --> 00:07:21,600 using these attributes, I can group 149 00:07:21,600 --> 00:07:24,790 these three objects together and these three objects together, 150 00:07:24,790 --> 00:07:25,290 OK? 151 00:07:29,500 --> 00:07:33,070 So I'm grouping sets of objects that 152 00:07:33,070 --> 00:07:37,190 are going to have the same attributes together. 153 00:07:37,190 --> 00:07:40,230 And attributes-- this is also a recap of last time-- come 154 00:07:40,230 --> 00:07:42,090 in two forms, right, data attributes 155 00:07:42,090 --> 00:07:44,900 and procedural attributes. 156 00:07:44,900 --> 00:07:49,280 So the data attributes are basically 157 00:07:49,280 --> 00:07:52,760 things that define what the object is. 158 00:07:52,760 --> 00:07:56,307 So how do you represent a cat as an object? 159 00:07:56,307 --> 00:07:57,890 And it's up to you, as the programmer, 160 00:07:57,890 --> 00:07:59,750 to decide how you want to do that. 161 00:07:59,750 --> 00:08:03,950 For a coordinate, it was pretty straightforward. 162 00:08:03,950 --> 00:08:06,529 You had an x and a y value. 163 00:08:06,529 --> 00:08:09,070 If we're representing something more abstract like an animal, 164 00:08:09,070 --> 00:08:10,445 then maybe I would say, well, I'm 165 00:08:10,445 --> 00:08:12,844 going to represent an animal by an age and a name, OK? 166 00:08:12,844 --> 00:08:14,260 So it's really up to you to decide 167 00:08:14,260 --> 00:08:20,980 how you want to represent-- what data attributes you want 168 00:08:20,980 --> 00:08:24,550 to represent your object with. 169 00:08:24,550 --> 00:08:28,690 Procedural attributes were also known as methods. 170 00:08:28,690 --> 00:08:33,020 And the methods are essentially asking, 171 00:08:33,020 --> 00:08:35,210 what can your object do, OK? 172 00:08:35,210 --> 00:08:37,789 So how can someone who wants to use your object-- how 173 00:08:37,789 --> 00:08:40,010 can someone interact with it? 174 00:08:40,010 --> 00:08:41,659 So for a coordinate, we saw that you 175 00:08:41,659 --> 00:08:43,820 could find the distance between two coordinates. 176 00:08:43,820 --> 00:08:47,180 Maybe for our abstract Animal object, 177 00:08:47,180 --> 00:08:49,700 you might have it make a sound, OK, 178 00:08:49,700 --> 00:08:53,920 by maybe printing to the screen or something like that. 179 00:08:53,920 --> 00:08:58,800 OK, this slide's also a recap of how to create a class just 180 00:08:58,800 --> 00:09:01,710 to make sure everyone's on the same page before we go on. 181 00:09:01,710 --> 00:09:04,770 So we defined a class using this class keyword. 182 00:09:04,770 --> 00:09:06,590 And we said, class, the name of the class. 183 00:09:06,590 --> 00:09:09,677 So now we're going to create a more abstract Animal class. 184 00:09:09,677 --> 00:09:11,260 We're going to see, in the second half 185 00:09:11,260 --> 00:09:13,390 of the lecture, what it means to put something 186 00:09:13,390 --> 00:09:14,390 else in the parentheses. 187 00:09:14,390 --> 00:09:23,620 But for now, we say that an animal is an object in Python. 188 00:09:23,620 --> 00:09:26,650 So that means it's going to have all of the properties 189 00:09:26,650 --> 00:09:29,740 that any other object in Python has. 190 00:09:29,740 --> 00:09:31,210 And as we're creating this animal, 191 00:09:31,210 --> 00:09:34,390 we're going to define how to create 192 00:09:34,390 --> 00:09:36,310 an instance of this class. 193 00:09:36,310 --> 00:09:38,050 So we say def. 194 00:09:38,050 --> 00:09:40,540 And this __init__ was the special method that told Python 195 00:09:40,540 --> 00:09:43,496 how to create an object. 196 00:09:43,496 --> 00:09:44,870 Inside the parentheses, remember, 197 00:09:44,870 --> 00:09:47,000 we have the self, which is a variable 198 00:09:47,000 --> 00:09:49,967 that we use to refer to any instance of the class, OK? 199 00:09:49,967 --> 00:09:51,800 We don't have a particular instance in mind, 200 00:09:51,800 --> 00:09:55,190 we just want to be able to refer to any instance, OK? 201 00:09:55,190 --> 00:09:58,442 So we use this self variable. 202 00:09:58,442 --> 00:09:59,900 And then, the second parameter here 203 00:09:59,900 --> 00:10:03,650 is going to represent what other data we use 204 00:10:03,650 --> 00:10:05,070 to initialize our object with. 205 00:10:05,070 --> 00:10:06,486 So in this case, I'm going to say, 206 00:10:06,486 --> 00:10:09,110 I'm going to initialize an Animal object with an age, OK? 207 00:10:09,110 --> 00:10:13,149 So when I create an animal, I need to give it an age. 208 00:10:13,149 --> 00:10:15,440 Inside the __init__ are any initializations that I want 209 00:10:15,440 --> 00:10:16,910 to make. 210 00:10:16,910 --> 00:10:19,580 So the first thing is, I'm going to assign an instance 211 00:10:19,580 --> 00:10:22,700 variable, age-- so this is going to be the data attribute 212 00:10:22,700 --> 00:10:24,990 age-- to be whatever is passed in. 213 00:10:24,990 --> 00:10:27,110 And then, I'm also making another assignment here, 214 00:10:27,110 --> 00:10:29,180 where I'm assigning the data attribute 215 00:10:29,180 --> 00:10:33,400 name to be None originally. 216 00:10:33,400 --> 00:10:35,740 Later on in the code, when I want to create an Animal 217 00:10:35,740 --> 00:10:38,320 object, I say the class name. 218 00:10:38,320 --> 00:10:41,080 And then I pass it in whatever parameters 219 00:10:41,080 --> 00:10:43,150 it takes-- in this case, the age. 220 00:10:43,150 --> 00:10:50,760 And I'm assigning it to this instance here, OK? 221 00:10:50,760 --> 00:10:54,990 All right, so now we have this class, Animal. 222 00:10:54,990 --> 00:10:57,810 We've done the first part here, which is 223 00:10:57,810 --> 00:11:01,260 to initialize the class, right? 224 00:11:01,260 --> 00:11:06,570 So we've told Python how to create an object of this type. 225 00:11:06,570 --> 00:11:11,340 There's a few other methods here that I've implemented. 226 00:11:11,340 --> 00:11:14,400 Next two we call getters, and the two 227 00:11:14,400 --> 00:11:17,480 after that we call setters, OK? 228 00:11:17,480 --> 00:11:19,920 And getters and setters are very commonly 229 00:11:19,920 --> 00:11:28,060 used when implementing a class. 230 00:11:28,060 --> 00:11:31,580 So getters essentially return the values of any 231 00:11:31,580 --> 00:11:35,600 of the data attributes, OK? 232 00:11:35,600 --> 00:11:40,290 So if you look carefully, get_age() is just returning 233 00:11:40,290 --> 00:11:44,640 self.age, and get_name() just returns self.name. 234 00:11:44,640 --> 00:11:47,880 So they're very simple methods. 235 00:11:47,880 --> 00:11:49,600 Similarly, set_age() and set_name()-- 236 00:11:49,600 --> 00:11:53,370 we're going to see what this funny equal sign is doing here 237 00:11:53,370 --> 00:11:55,020 in the next couple of slides. 238 00:11:55,020 --> 00:11:56,520 But setters do a very similar thing 239 00:11:56,520 --> 00:11:58,436 where they're going to set the data attributes 240 00:11:58,436 --> 00:12:00,927 to whatever is passed in, OK? 241 00:12:04,600 --> 00:12:06,670 So those are getters and setters. 242 00:12:06,670 --> 00:12:09,420 And then, the last thing down here is this __str__ method. 243 00:12:09,420 --> 00:12:13,530 And this __str__ method is used to tell Python how to print 244 00:12:13,530 --> 00:12:15,951 an object of this type Animal. 245 00:12:15,951 --> 00:12:17,700 So if you didn't have this __str__ method, 246 00:12:17,700 --> 00:12:19,230 if you remember from last lecture, 247 00:12:19,230 --> 00:12:23,880 what ends up happening is you're going to get some message when 248 00:12:23,880 --> 00:12:27,420 you print your object that says, this is an object of type 249 00:12:27,420 --> 00:12:30,810 Animal at this memory location, which is very uninformative, 250 00:12:30,810 --> 00:12:31,710 right? 251 00:12:31,710 --> 00:12:33,300 So you implement this method here, 252 00:12:33,300 --> 00:12:40,319 which tells Python how to print an object of this type, OK? 253 00:12:40,319 --> 00:12:43,407 So the big point of this slide is 254 00:12:43,407 --> 00:12:45,490 that you should be using getters and setters-- you 255 00:12:45,490 --> 00:12:49,340 should be implementing getters and setters for your classes. 256 00:12:49,340 --> 00:12:52,440 And we're going to see, in the next couple of slides, 257 00:12:52,440 --> 00:12:54,390 why exactly. 258 00:12:54,390 --> 00:12:57,660 But basically, they're going to prevent bugs 259 00:12:57,660 --> 00:13:01,410 from coming into play later on if someone decides 260 00:13:01,410 --> 00:13:04,150 to change implementation. 261 00:13:04,150 --> 00:13:06,179 So we saw how to-- so the previous slide, 262 00:13:06,179 --> 00:13:08,470 this slide here, shows the implementation of the Animal 263 00:13:08,470 --> 00:13:09,790 class. 264 00:13:09,790 --> 00:13:12,550 And here we can see how we can create 265 00:13:12,550 --> 00:13:14,830 an instance of this object. 266 00:13:14,830 --> 00:13:16,740 So we can say a = Animal(3). 267 00:13:16,740 --> 00:13:20,800 So this is going to create a new Animal object with an age of 3. 268 00:13:20,800 --> 00:13:25,390 And we can access the object through the variable a. 269 00:13:25,390 --> 00:13:27,250 Dot notation, recall, is a way for you 270 00:13:27,250 --> 00:13:31,120 to access data attributes and methods of a class, OK? 271 00:13:31,120 --> 00:13:34,660 So you can say a.age later on in your program, 272 00:13:34,660 --> 00:13:36,390 and that is allowed. 273 00:13:36,390 --> 00:13:38,530 It'll try to access the age data attribute 274 00:13:38,530 --> 00:13:41,440 of this particular instance of the class, a. 275 00:13:41,440 --> 00:13:44,460 So this is going to give you 3. 276 00:13:44,460 --> 00:13:47,580 However, it's actually not recommended to access 277 00:13:47,580 --> 00:13:48,760 data attributes directly. 278 00:13:48,760 --> 00:13:50,280 So this is the reason-- so you're 279 00:13:50,280 --> 00:13:52,780 going to see in the next slide, the reason-- why we're going 280 00:13:52,780 --> 00:13:53,940 to use getters and setters. 281 00:13:53,940 --> 00:13:59,710 Instead, you should use the get_age() getter method to get 282 00:13:59,710 --> 00:14:02,840 the age of the animal. 283 00:14:02,840 --> 00:14:04,404 So this is going to return, also, 3. 284 00:14:04,404 --> 00:14:06,070 So these are going to do the same thing. 285 00:14:09,900 --> 00:14:12,720 And the reason why you'd want to use getters and setters 286 00:14:12,720 --> 00:14:15,579 is this idea of information hiding, OK? 287 00:14:15,579 --> 00:14:17,370 So the whole reason why we're using classes 288 00:14:17,370 --> 00:14:19,590 in object-oriented programming is 289 00:14:19,590 --> 00:14:24,690 so that you can abstract certain data from the user, OK? 290 00:14:24,690 --> 00:14:26,880 One of the things you should be abstracting 291 00:14:26,880 --> 00:14:29,340 is these data attributes. 292 00:14:29,340 --> 00:14:31,170 So users shouldn't really need to know 293 00:14:31,170 --> 00:14:33,360 how a class is implemented. 294 00:14:33,360 --> 00:14:36,450 They should just know how to use the class, OK? 295 00:14:36,450 --> 00:14:37,890 So consider the following case. 296 00:14:37,890 --> 00:14:41,280 Let's say whoever wrote the Animal class wants 297 00:14:41,280 --> 00:14:43,662 to change the implementation. 298 00:14:43,662 --> 00:14:45,120 And they've decided they don't want 299 00:14:45,120 --> 00:14:47,070 to call the data attribute "age" anymore, they 300 00:14:47,070 --> 00:14:48,900 want to call it "years," OK? 301 00:14:48,900 --> 00:14:50,430 So when they initialize an animal 302 00:14:50,430 --> 00:14:53,970 they say self.years = age. 303 00:14:53,970 --> 00:14:58,140 So an animal still gets initialized by its age. 304 00:14:58,140 --> 00:15:03,070 And the age gets passed into a data attribute named "years," 305 00:15:03,070 --> 00:15:04,580 OK? 306 00:15:04,580 --> 00:15:06,200 Since I'm implementing this class, 307 00:15:06,200 --> 00:15:08,930 I want to have a getter, which is going to return self.years. 308 00:15:08,930 --> 00:15:11,180 So I'm not returning self.age anymore, 309 00:15:11,180 --> 00:15:15,990 because age is no longer the data attribute I'm using. 310 00:15:15,990 --> 00:15:20,310 So with this new implementation, if someone 311 00:15:20,310 --> 00:15:23,820 was using this implementation and was accessing age directly 312 00:15:23,820 --> 00:15:27,940 as-- was accessing the data attribute age directly-- 313 00:15:27,940 --> 00:15:29,440 with this new implementation, they'd 314 00:15:29,440 --> 00:15:31,030 actually get an error, right? 315 00:15:31,030 --> 00:15:33,190 Because this animal that they created 316 00:15:33,190 --> 00:15:35,560 using my old implementation no longer 317 00:15:35,560 --> 00:15:37,870 has an attribute named "age." 318 00:15:37,870 --> 00:15:39,850 And so Python's going to spit out 319 00:15:39,850 --> 00:15:42,385 an error saying no attribute found or something like that, 320 00:15:42,385 --> 00:15:43,280 OK? 321 00:15:43,280 --> 00:15:46,270 If they were using the getter a.get_age()-- 322 00:15:46,270 --> 00:15:49,060 the person who implemented the class re-implemented get_age() 323 00:15:49,060 --> 00:15:55,480 to work correctly, right, with their new data attribute, 324 00:15:55,480 --> 00:15:59,940 years, as opposed to age-- so if I was using the getter 325 00:15:59,940 --> 00:16:03,670 get_age(), I wouldn't have run into the bug, OK? 326 00:16:03,670 --> 00:16:09,060 So things to remember-- write getters and setters 327 00:16:09,060 --> 00:16:10,410 for your classes. 328 00:16:10,410 --> 00:16:12,990 And later on in your code, use getters and setters 329 00:16:12,990 --> 00:16:19,750 to prevent bugs and to promote easy to maintain code. 330 00:16:19,750 --> 00:16:25,009 OK, so information hiding is great. 331 00:16:25,009 --> 00:16:26,800 But having said that, Python's actually not 332 00:16:26,800 --> 00:16:29,290 very great at information hiding, OK? 333 00:16:29,290 --> 00:16:31,060 Python allows you to do certain things 334 00:16:31,060 --> 00:16:33,280 that you should never be doing. 335 00:16:33,280 --> 00:16:34,120 OK. 336 00:16:34,120 --> 00:16:37,180 So the first, we've just seen. 337 00:16:37,180 --> 00:16:39,790 The first is to access data attributes 338 00:16:39,790 --> 00:16:42,490 from outside of the class, OK? 339 00:16:42,490 --> 00:16:45,010 So if I were to say a.age, Python 340 00:16:45,010 --> 00:16:49,700 allows me to do that without using a getter and setter. 341 00:16:49,700 --> 00:16:53,900 Python also allows you to write to data attributes 342 00:16:53,900 --> 00:16:56,250 from outside the class. 343 00:16:56,250 --> 00:16:58,620 So if I implemented the class Animal 344 00:16:58,620 --> 00:17:02,110 assuming that age was a number, an integer, 345 00:17:02,110 --> 00:17:05,770 and all of my methods work as long as age is an integer, 346 00:17:05,770 --> 00:17:09,260 but someone decided to be smart and, outside of the class, 347 00:17:09,260 --> 00:17:14,230 set age to be infinite as a string, that might 348 00:17:14,230 --> 00:17:17,020 cause the code to crash, OK? 349 00:17:17,020 --> 00:17:18,790 Python allows you to do that. 350 00:17:18,790 --> 00:17:22,750 But now you're breaking the fact that age 351 00:17:22,750 --> 00:17:24,364 has to be an integer, right? 352 00:17:24,364 --> 00:17:25,780 So now the methods should probably 353 00:17:25,780 --> 00:17:28,154 be checking the fact that age is an integer all the time. 354 00:17:30,702 --> 00:17:32,410 The other thing that you're allowed to do 355 00:17:32,410 --> 00:17:35,890 is to create data attributes outside of the class 356 00:17:35,890 --> 00:17:37,540 definition, OK? 357 00:17:37,540 --> 00:17:40,480 So if I wanted to create a new data attribute called "size" 358 00:17:40,480 --> 00:17:42,370 for this particular instance, Python also 359 00:17:42,370 --> 00:17:43,790 allows me to do that. 360 00:17:43,790 --> 00:17:46,547 And I can set it to whatever I want, OK? 361 00:17:46,547 --> 00:17:48,380 So Python allows you to do all these things, 362 00:17:48,380 --> 00:17:52,590 but it's actually not good style to do any of them. 363 00:17:52,590 --> 00:17:56,220 So just don't do it. 364 00:17:56,220 --> 00:17:58,394 All right. 365 00:17:58,394 --> 00:18:00,560 So the last thing I want to mention-- the last thing 366 00:18:00,560 --> 00:18:02,840 about classes before we go on to inheritance-- 367 00:18:02,840 --> 00:18:05,660 is this idea called default arguments. 368 00:18:05,660 --> 00:18:09,011 And default arguments are passed into methods. 369 00:18:09,011 --> 00:18:10,510 And since methods are functions, you 370 00:18:10,510 --> 00:18:14,590 can also pass in different arguments to functions. 371 00:18:14,590 --> 00:18:17,650 So for example, this set_name() method had self. 372 00:18:17,650 --> 00:18:22,720 And then, this new name is equal to this empty string here, OK? 373 00:18:22,720 --> 00:18:26,152 We haven't seen this before. 374 00:18:26,152 --> 00:18:27,735 But this is called a default argument. 375 00:18:30,390 --> 00:18:33,615 And you can use the function in one of two ways. 376 00:18:37,240 --> 00:18:38,940 The first way is so we can create 377 00:18:38,940 --> 00:18:42,900 a new instance of an Animal type object with this line 378 00:18:42,900 --> 00:18:46,360 here, a = Animal(3). 379 00:18:46,360 --> 00:18:48,230 And then we can say a.set_name(). 380 00:18:48,230 --> 00:18:52,360 So this calls the setter method to set the name. 381 00:18:52,360 --> 00:18:55,470 And notice, we've always said that you 382 00:18:55,470 --> 00:19:00,270 have to put in parameters for everything other than self, OK? 383 00:19:00,270 --> 00:19:04,240 But here we have no parameters passed in. 384 00:19:04,240 --> 00:19:07,890 But that's OK, because newname actually 385 00:19:07,890 --> 00:19:11,440 has a default argument, OK? 386 00:19:11,440 --> 00:19:15,490 So that tells Python, if no parameter is passed in for this 387 00:19:15,490 --> 00:19:19,570 particular formal parameter, then use whatever is up here 388 00:19:19,570 --> 00:19:23,160 by default. So if I haven't passed in the parameter 389 00:19:23,160 --> 00:19:27,610 a.get_na-- a.set_name(), sorry-- a.sett_name() is going to be 390 00:19:27,610 --> 00:19:29,290 setting the name to the empty string, 391 00:19:29,290 --> 00:19:32,030 because that's what the default parameter is. 392 00:19:32,030 --> 00:19:34,120 So in the next line, when I print a.get_name(), 393 00:19:34,120 --> 00:19:36,380 this is just going to print the empty string, OK? 394 00:19:39,340 --> 00:19:41,170 If you do want to pass in a parameter, 395 00:19:41,170 --> 00:19:43,720 you can do so as normal. 396 00:19:43,720 --> 00:19:46,090 So you can say a = Animal(3), a.set_name(), 397 00:19:46,090 --> 00:19:48,610 and then pass in a parameter here. 398 00:19:48,610 --> 00:19:52,195 And then, newname is going to be assigned to whatever parameter 399 00:19:52,195 --> 00:19:55,890 is passed in like that. 400 00:19:55,890 --> 00:19:59,010 Whatever you pass in overrides the default argument, 401 00:19:59,010 --> 00:20:00,997 and everything is good. 402 00:20:00,997 --> 00:20:03,330 So when I print a.get_name(), this is going to print out 403 00:20:03,330 --> 00:20:05,010 the name that you've passed in. 404 00:20:08,350 --> 00:20:10,177 Questions about default? 405 00:20:10,177 --> 00:20:11,151 Yeah. 406 00:20:11,151 --> 00:20:12,125 AUDIENCE: [INAUDIBLE] 407 00:20:16,055 --> 00:20:18,430 ANA BELL: What if you don't provide a default value for-- 408 00:20:18,430 --> 00:20:19,750 AUDIENCE: For newname? 409 00:20:19,750 --> 00:20:20,666 ANA BELL: For newname? 410 00:20:22,560 --> 00:20:24,960 If you don't provide a default argument for newname 411 00:20:24,960 --> 00:20:27,600 and you do this case here, then that's 412 00:20:27,600 --> 00:20:28,750 going to give you an error. 413 00:20:28,750 --> 00:20:30,416 So Python's going to say something like, 414 00:20:30,416 --> 00:20:33,325 expected one argument, got zero, or something like that. 415 00:20:33,325 --> 00:20:33,950 Great question. 416 00:20:37,537 --> 00:20:39,900 OK. 417 00:20:39,900 --> 00:20:42,834 All right, so let's move on to this idea of hierarchies, OK? 418 00:20:42,834 --> 00:20:45,000 So the great thing about object-oriented programming 419 00:20:45,000 --> 00:20:47,520 is that it allows us to add layers of abstraction 420 00:20:47,520 --> 00:20:48,490 to our code, all right? 421 00:20:48,490 --> 00:20:52,140 So we don't need to know how very, very low-level things are 422 00:20:52,140 --> 00:20:53,820 implemented in order to use them. 423 00:20:53,820 --> 00:20:59,490 And we can build up our code to be more and more complex 424 00:20:59,490 --> 00:21:04,140 as we use up these different abstractions. 425 00:21:04,140 --> 00:21:08,700 So consider every one of these things on this slide as being 426 00:21:08,700 --> 00:21:10,950 a separate object, all right? 427 00:21:10,950 --> 00:21:15,993 Every one of these things can be considered to be an animal, OK? 428 00:21:19,690 --> 00:21:21,760 According to our implementation of an animal, 429 00:21:21,760 --> 00:21:24,400 the one thing that an animal has is an age, OK? 430 00:21:24,400 --> 00:21:26,170 And that's probably true, right? 431 00:21:26,170 --> 00:21:28,860 Every one of these things has an age. 432 00:21:28,860 --> 00:21:31,630 But now I want to build up on this 433 00:21:31,630 --> 00:21:33,580 and create separate groups, right? 434 00:21:33,580 --> 00:21:35,350 And each one of these separate groups 435 00:21:35,350 --> 00:21:37,990 that I create on top of Animal is 436 00:21:37,990 --> 00:21:40,099 going to have its own functionality, right? 437 00:21:40,099 --> 00:21:42,640 They're going to be a little bit more specific, a little more 438 00:21:42,640 --> 00:21:44,560 specialized. 439 00:21:44,560 --> 00:21:47,410 So I can create these three groups now, a cat, a rabbit, 440 00:21:47,410 --> 00:21:50,360 and a person group. 441 00:21:50,360 --> 00:21:53,510 And for example-- so they're all animals, right? 442 00:21:53,510 --> 00:21:55,750 They all have an age. 443 00:21:55,750 --> 00:21:57,310 But for example, maybe a person's 444 00:21:57,310 --> 00:22:00,730 going to have a list of friends whereas a cat and a rabbit 445 00:22:00,730 --> 00:22:02,660 do not. 446 00:22:02,660 --> 00:22:07,280 Maybe a cat has a data attribute for the number of lives 447 00:22:07,280 --> 00:22:11,690 they have left, right, whereas a person and a rabbit do not, OK? 448 00:22:11,690 --> 00:22:16,580 So you can think of adding these more specialized-- adding 449 00:22:16,580 --> 00:22:19,339 functionality to each one of these subgroups, OK? 450 00:22:19,339 --> 00:22:21,380 So they're going to be more and more specialized, 451 00:22:21,380 --> 00:22:24,055 but all of them retaining the fact that they are animals. 452 00:22:24,055 --> 00:22:28,160 So they all have an age, for example. 453 00:22:28,160 --> 00:22:31,930 So on top of these, we can add another layer 454 00:22:31,930 --> 00:22:36,590 and say that a student is a person and is an animal, OK? 455 00:22:36,590 --> 00:22:39,910 But in addition to having an age and maybe also having a list 456 00:22:39,910 --> 00:22:42,430 of friends, a student might also have a major 457 00:22:42,430 --> 00:22:46,720 or-- they're pretty, so maybe-- their favorite subject 458 00:22:46,720 --> 00:22:47,220 in school. 459 00:22:52,290 --> 00:22:55,310 So that's the general idea of hierarchies, OK? 460 00:22:55,310 --> 00:23:02,000 So we can sort of abstract the previous slide into this one 461 00:23:02,000 --> 00:23:05,570 and say that we have parent classes and child classes, OK? 462 00:23:05,570 --> 00:23:07,890 The Animal class is like our parent class. 463 00:23:07,890 --> 00:23:09,220 It's the highest-level class. 464 00:23:13,480 --> 00:23:15,580 Inheriting from the Animal class, 465 00:23:15,580 --> 00:23:19,380 we have these child classes or subclasses, OK? 466 00:23:19,380 --> 00:23:21,684 Whatever an animal can do, a person can do. 467 00:23:21,684 --> 00:23:23,350 Whatever an animal can do, a cat can do. 468 00:23:23,350 --> 00:23:26,430 And whatever an animal can do, a rabbit can do, OK-- that is, 469 00:23:26,430 --> 00:23:31,530 have an age and maybe some really basic functionality, OK? 470 00:23:31,530 --> 00:23:33,300 But between person, cat, and rabbit, 471 00:23:33,300 --> 00:23:34,890 they're going to be varying wildly 472 00:23:34,890 --> 00:23:36,973 as to the kinds of things that they can do, right? 473 00:23:36,973 --> 00:23:40,070 But they can all do whatever Animal can do. 474 00:23:40,070 --> 00:23:43,010 So child classes inherit all of the data attributes 475 00:23:43,010 --> 00:23:44,750 and all of the methods, or behaviors, 476 00:23:44,750 --> 00:23:48,610 that their parent's classes have, OK? 477 00:23:48,610 --> 00:23:50,800 But child classes can add more information. 478 00:23:50,800 --> 00:23:53,290 Like for example, a person can have a list of friends 479 00:23:53,290 --> 00:23:55,030 whereas a general animal will not. 480 00:23:58,790 --> 00:24:00,140 It can add more behavior. 481 00:24:00,140 --> 00:24:03,170 Like, maybe a cat can climb trees whereas people 482 00:24:03,170 --> 00:24:05,820 and rabbits cannot. 483 00:24:05,820 --> 00:24:07,990 Or you can also override behavior. 484 00:24:07,990 --> 00:24:11,430 So in the previous one, we had animal, person, student. 485 00:24:11,430 --> 00:24:13,770 So maybe we have, an animal doesn't speak at all, 486 00:24:13,770 --> 00:24:15,420 but a person can speak. 487 00:24:15,420 --> 00:24:18,420 So that's added functionality to the person. 488 00:24:18,420 --> 00:24:20,340 And maybe a person can only say hello. 489 00:24:20,340 --> 00:24:21,840 But then, when we talk to a student, 490 00:24:21,840 --> 00:24:25,590 we can override the fact-- override the speak() method 491 00:24:25,590 --> 00:24:28,800 of a person and say that a student can say, you know, 492 00:24:28,800 --> 00:24:31,550 I have homework, or I need sleep, or something like that, 493 00:24:31,550 --> 00:24:32,550 OK? 494 00:24:32,550 --> 00:24:35,162 So we have the same speak() method for both person 495 00:24:35,162 --> 00:24:36,870 and student, because they can both speak. 496 00:24:36,870 --> 00:24:38,559 But student will override the fact 497 00:24:38,559 --> 00:24:40,225 that they say hello with something else. 498 00:24:42,790 --> 00:24:47,360 OK, so let's look at some code to put this into perspective. 499 00:24:47,360 --> 00:24:52,290 So we have this Animal class, which we've seen before. 500 00:24:52,290 --> 00:24:54,500 This is the parent class, OK? 501 00:24:54,500 --> 00:24:58,130 It inherits from object, which means that everything 502 00:24:58,130 --> 00:25:01,670 that a basic object can do in Python, an animal can do, 503 00:25:01,670 --> 00:25:04,000 which is things like binding variables, 504 00:25:04,000 --> 00:25:06,831 you know, very low-level things, OK? 505 00:25:06,831 --> 00:25:07,830 We've seen the __init__. 506 00:25:07,830 --> 00:25:11,820 We've seen the two getters, the setters, and the string method 507 00:25:11,820 --> 00:25:15,750 to print an object of type Animal. 508 00:25:15,750 --> 00:25:18,330 All right, now, let's create a subclass of Animal. 509 00:25:18,330 --> 00:25:22,440 We'll call it Cat, OK? 510 00:25:22,440 --> 00:25:25,697 We create a class named Cat. 511 00:25:25,697 --> 00:25:27,530 In parentheses, instead of putting "object," 512 00:25:27,530 --> 00:25:29,200 we now put "Animal." 513 00:25:29,200 --> 00:25:34,870 And this tells Python that Cat's parent class is Animal. 514 00:25:34,870 --> 00:25:37,900 So everything that an animal can do, a cat can do. 515 00:25:37,900 --> 00:25:40,120 So that includes all of the attributes, which 516 00:25:40,120 --> 00:25:42,650 was age and name, and all of the methods. 517 00:25:42,650 --> 00:25:45,490 So all the getters, the setters, the __str__, the __init__, 518 00:25:45,490 --> 00:25:48,160 everything that the animal had, now the cat has-- 519 00:25:48,160 --> 00:25:51,700 the Cat class has. 520 00:25:51,700 --> 00:25:55,730 In the Cat class, we're going to add two more methods though. 521 00:25:55,730 --> 00:25:59,190 The first is speak(). 522 00:25:59,190 --> 00:26:04,980 So speak() is going to be a method that's going to just 523 00:26:04,980 --> 00:26:08,920 take in the self, OK-- no other parameters. 524 00:26:08,920 --> 00:26:11,710 And all it's doing is printing "meow" to the screen-- very 525 00:26:11,710 --> 00:26:13,150 simple, OK? 526 00:26:13,150 --> 00:26:15,760 So through this speak(), we've added new functionality 527 00:26:15,760 --> 00:26:17,080 to the class. 528 00:26:17,080 --> 00:26:22,690 So an animal couldn't speak, whereas a cat says "meow." 529 00:26:22,690 --> 00:26:25,000 Additionally, through this __str__ method here, 530 00:26:25,000 --> 00:26:28,240 we're overriding the animal __str__, OK? 531 00:26:28,240 --> 00:26:30,320 So if we go back to the previous slide, 532 00:26:30,320 --> 00:26:34,210 we can see that the animal's __str__ had animal, 533 00:26:34,210 --> 00:26:40,900 plus the name, plus the age here whereas the cat's __str__ now 534 00:26:40,900 --> 00:26:44,510 says "cat," name, and the age, OK? 535 00:26:44,510 --> 00:26:48,270 So this is just how I chose to implement this, OK? 536 00:26:48,270 --> 00:26:51,330 So here I've overridden the __str__ method of the Animal 537 00:26:51,330 --> 00:26:53,690 class. 538 00:26:53,690 --> 00:26:56,450 Notice that this class doesn't have an __init__, 539 00:26:56,450 --> 00:26:57,690 and that's OK. 540 00:26:57,690 --> 00:27:01,070 Because Python's actually going to say, well, 541 00:27:01,070 --> 00:27:04,430 if there's no __init__ in this particular method-- sorry, 542 00:27:04,430 --> 00:27:09,770 in this particular class-- then look to my parents and say, 543 00:27:09,770 --> 00:27:11,780 do my parents have an __init__, OK? 544 00:27:11,780 --> 00:27:15,540 And if so, use that __init__. 545 00:27:15,540 --> 00:27:17,617 So that's actually true for any other methods. 546 00:27:20,770 --> 00:27:23,840 So the idea here is, when you have hierarchies, 547 00:27:23,840 --> 00:27:26,799 you have a parent class, you have a child class, 548 00:27:26,799 --> 00:27:28,840 you could have a child class to that child class, 549 00:27:28,840 --> 00:27:29,910 and so on and so on. 550 00:27:29,910 --> 00:27:33,930 So you can have multiple levels of inheritance. 551 00:27:33,930 --> 00:27:35,900 What happens when you create an object that 552 00:27:35,900 --> 00:27:40,000 is of type something that's been-- of a type that's 553 00:27:40,000 --> 00:27:43,700 the child class of a child class of a child class, right? 554 00:27:43,700 --> 00:27:47,900 What happens when you call a method on that object? 555 00:27:47,900 --> 00:27:50,510 Well, Python's are going to say, does a method with 556 00:27:50,510 --> 00:27:53,120 that name exist in my current class definition? 557 00:27:53,120 --> 00:27:54,750 And if so, use that. 558 00:27:54,750 --> 00:27:56,390 But if not, then, look to my parents. 559 00:27:56,390 --> 00:27:59,060 Do my parents know how to do that, right? 560 00:27:59,060 --> 00:28:04,010 Do my parents have a method for whatever I want to do? 561 00:28:04,010 --> 00:28:04,820 If so, use that. 562 00:28:04,820 --> 00:28:07,100 If not, look to their parents, and so on and so on. 563 00:28:07,100 --> 00:28:09,950 So you're sort of tracing back up your ancestry 564 00:28:09,950 --> 00:28:14,630 to figure out if you can do this method or not. 565 00:28:14,630 --> 00:28:18,270 So let's look at a slightly more complicated example. 566 00:28:18,270 --> 00:28:19,880 We have a class named Person. 567 00:28:19,880 --> 00:28:21,296 It's going to inherit from Animal. 568 00:28:24,680 --> 00:28:27,500 Inside this person, I'm going to create my own-- 569 00:28:27,500 --> 00:28:29,510 I'm going to create an __init__ method. 570 00:28:29,510 --> 00:28:32,134 And the __init__ method is going to do something different than 571 00:28:32,134 --> 00:28:34,370 what the animal's __init__ method is doing. 572 00:28:34,370 --> 00:28:36,170 It's going to take in self, as usual. 573 00:28:36,170 --> 00:28:38,294 And it's going to take in two parameters as opposed 574 00:28:38,294 --> 00:28:41,309 to one, a name and an age. 575 00:28:41,309 --> 00:28:43,600 First thing the __init__ method's doing is it's calling 576 00:28:43,600 --> 00:28:46,090 the animal's __init__ method. 577 00:28:46,090 --> 00:28:48,040 Why am I doing that? 578 00:28:48,040 --> 00:28:53,040 Well, I could theoretically initialize the name 579 00:28:53,040 --> 00:28:55,350 and the age data attributes that Animal 580 00:28:55,350 --> 00:28:58,570 initializes in this method. 581 00:28:58,570 --> 00:29:00,630 But I'm using the fact that I've already 582 00:29:00,630 --> 00:29:03,420 written code that initializes those two data attributes. 583 00:29:03,420 --> 00:29:05,790 So why not just use it, OK? 584 00:29:05,790 --> 00:29:08,910 So here, this says, I'm going to call the class Animal. 585 00:29:08,910 --> 00:29:10,800 I'm going to call its __init__ method. 586 00:29:10,800 --> 00:29:14,550 And I'm going to leave it up to you to-- not you as the class, 587 00:29:14,550 --> 00:29:18,645 but I'm talking as the programs is running-- 588 00:29:18,645 --> 00:29:20,520 I'm going to leave it up to you to figure out 589 00:29:20,520 --> 00:29:24,840 how to initialize an animal with this particular age 590 00:29:24,840 --> 00:29:26,051 and what to name it. 591 00:29:28,640 --> 00:29:31,110 So Python says, yep, I know how to do this, 592 00:29:31,110 --> 00:29:33,470 so I'm going to go ahead and do that for you. 593 00:29:33,470 --> 00:29:35,900 So now it says person is an animal. 594 00:29:35,900 --> 00:29:38,760 And I've initialized the age and the name for you. 595 00:29:38,760 --> 00:29:41,260 The next thing I'm doing in the __init__ is I'm going to set 596 00:29:41,260 --> 00:29:44,752 the name to whatever name was passed in, OK? 597 00:29:44,752 --> 00:29:46,960 So in the __init__, notice, I can do whatever I want, 598 00:29:46,960 --> 00:29:50,805 including calling methods. 599 00:29:50,805 --> 00:29:52,430 And then, the last thing I'm doing here 600 00:29:52,430 --> 00:29:55,250 is I'm going to create a new data attribute for Person, 601 00:29:55,250 --> 00:29:57,899 which is a list of friends, OK? 602 00:29:57,899 --> 00:29:59,690 So an animal didn't have a list of friends, 603 00:29:59,690 --> 00:30:01,721 but a person is going to. 604 00:30:04,550 --> 00:30:07,727 The next four methods here are-- this one's a getter, 605 00:30:07,727 --> 00:30:09,560 so it's going to return the list of friends. 606 00:30:09,560 --> 00:30:14,750 This is going to append a friend to the end of my list. 607 00:30:14,750 --> 00:30:17,420 I want to make a note that I actually didn't write a method 608 00:30:17,420 --> 00:30:18,300 to remove friends. 609 00:30:18,300 --> 00:30:21,290 So once you get a friend, they're friends for life. 610 00:30:21,290 --> 00:30:24,200 But that's OK. 611 00:30:24,200 --> 00:30:27,590 The next method here is speak(), which is going to print "hello" 612 00:30:27,590 --> 00:30:29,690 to the screen. 613 00:30:29,690 --> 00:30:31,306 And the last method here is going 614 00:30:31,306 --> 00:30:33,180 to get the age difference between two people. 615 00:30:33,180 --> 00:30:34,930 So that just basically subtracts their age 616 00:30:34,930 --> 00:30:38,730 and says it's a five-year age difference, or whatever it is. 617 00:30:38,730 --> 00:30:40,750 And down here, I have an __str__ method, 618 00:30:40,750 --> 00:30:42,700 which I've overridden from the Animal, which, 619 00:30:42,700 --> 00:30:46,630 instead of "animal: name," it's going to say "person: name : 620 00:30:46,630 --> 00:30:47,466 age," OK? 621 00:30:52,820 --> 00:30:54,760 So we can run this code. 622 00:30:54,760 --> 00:30:56,300 So that's down here. 623 00:30:56,300 --> 00:31:03,670 I have an animal person here. 624 00:31:07,690 --> 00:31:10,850 So I'm going to run this code. 625 00:31:10,850 --> 00:31:13,180 And what did I do? 626 00:31:13,180 --> 00:31:14,290 I created a new person. 627 00:31:14,290 --> 00:31:16,210 I gave it a name and an age. 628 00:31:16,210 --> 00:31:18,220 I created another person, a name and an age. 629 00:31:18,220 --> 00:31:19,990 And here I've just run some methods on it, 630 00:31:19,990 --> 00:31:22,540 which was get_name(), get_age(), get_name(), 631 00:31:22,540 --> 00:31:25,090 and get_age() for each of the two people. 632 00:31:25,090 --> 00:31:29,490 So that printed, Jack is 30, Jill is 25. 633 00:31:29,490 --> 00:31:32,190 If I print p1, this is going to use the __str__ method 634 00:31:32,190 --> 00:31:32,789 of Person. 635 00:31:32,789 --> 00:31:34,830 So it's to print "person:", their name, and then, 636 00:31:34,830 --> 00:31:36,540 their age. 637 00:31:36,540 --> 00:31:38,310 p1.speak() just says "hello." 638 00:31:38,310 --> 00:31:41,940 And then, the age difference between p1 and p2 is just 5. 639 00:31:41,940 --> 00:31:44,897 So that's just subtracting and then printing that out 640 00:31:44,897 --> 00:31:45,480 to the screen. 641 00:31:49,408 --> 00:31:50,680 OK, so that's my person. 642 00:31:53,560 --> 00:31:57,040 Let's add another class. 643 00:31:57,040 --> 00:31:58,950 This class is going to be a student, 644 00:31:58,950 --> 00:32:02,850 and it's going to be a subclass of Person. 645 00:32:02,850 --> 00:32:04,770 Since it's a subclass of Person, it's 646 00:32:04,770 --> 00:32:07,670 going to-- a student is going inherit 647 00:32:07,670 --> 00:32:11,360 all the attributes of a person, and therefore, all the 648 00:32:11,360 --> 00:32:14,780 attributes of an animal. 649 00:32:14,780 --> 00:32:17,270 The __init__ method of a student is going to be a little 650 00:32:17,270 --> 00:32:19,550 different from the one of Person. 651 00:32:19,550 --> 00:32:22,540 We're going to give it a name, an age, and a major. 652 00:32:22,540 --> 00:32:25,610 Notice we're using default arguments here. 653 00:32:25,610 --> 00:32:27,965 So if I create a student without giving it a major, 654 00:32:27,965 --> 00:32:32,990 the major is going to be set to None originally. 655 00:32:32,990 --> 00:32:37,730 Once again, this line here, Person. init (self, name, age), 656 00:32:37,730 --> 00:32:40,430 tells Python, hey, you already know 657 00:32:40,430 --> 00:32:44,120 how to initialize a person for me with this name and this age. 658 00:32:44,120 --> 00:32:46,370 So can you just do that? 659 00:32:46,370 --> 00:32:48,740 And Python says, yes, I can do that for you. 660 00:32:48,740 --> 00:32:51,844 And so that saves you, maybe, like five lines of code just 661 00:32:51,844 --> 00:32:54,260 by calling the __init__ method that you've already written 662 00:32:54,260 --> 00:32:56,870 through Person, OK? 663 00:32:56,870 --> 00:33:00,680 So Student has been initialized to be a person. 664 00:33:00,680 --> 00:33:03,140 And additionally, we're going to set another data attribute 665 00:33:03,140 --> 00:33:04,640 for the student to be the major. 666 00:33:04,640 --> 00:33:08,860 And we're going to set the major to be None. 667 00:33:08,860 --> 00:33:12,640 The student is going to get this setter here, this setter 668 00:33:12,640 --> 00:33:15,460 method, which is going to change the major to whatever 669 00:33:15,460 --> 00:33:19,850 else they want if they want to change it. 670 00:33:19,850 --> 00:33:24,910 And then, I'm going to override the speak() method. 671 00:33:24,910 --> 00:33:26,500 So the speak method for the person, 672 00:33:26,500 --> 00:33:28,210 recall, just said "hello." 673 00:33:28,210 --> 00:33:31,180 A student is going to be a little bit more complex. 674 00:33:31,180 --> 00:33:33,760 I'm going to use the fact that someone 675 00:33:33,760 --> 00:33:36,300 created this random class, OK? 676 00:33:36,300 --> 00:33:38,920 So this is where we can write more interesting code 677 00:33:38,920 --> 00:33:41,580 by reusing code that other people have written. 678 00:33:41,580 --> 00:33:43,480 So someone wrote a random class that 679 00:33:43,480 --> 00:33:47,430 can do cool things with random numbers. 680 00:33:47,430 --> 00:33:49,871 So if I want to use random numbers in my code, 681 00:33:49,871 --> 00:33:52,370 I'm going to put this "import random" at the top of my code, 682 00:33:52,370 --> 00:33:54,953 which essentially brings in all of the methods from the Random 683 00:33:54,953 --> 00:33:58,910 class, one of the methods being this random() method. 684 00:33:58,910 --> 00:34:04,840 So random() is a random() method from the Random class. 685 00:34:04,840 --> 00:34:07,800 And this essentially gives me a number between 0 and 1, 686 00:34:07,800 --> 00:34:11,440 including 0 but not including 1, OK? 687 00:34:11,440 --> 00:34:14,770 So this random number I get here is going to help me write 688 00:34:14,770 --> 00:34:18,844 my method for speak(), where it's going to-- with 25% 689 00:34:18,844 --> 00:34:21,219 probability, it's either going to say, "I have homework," 690 00:34:21,219 --> 00:34:24,400 "I need sleep," "I should eat," or "I'm watching TV," OK? 691 00:34:24,400 --> 00:34:27,052 So a student is going to say one of those four things. 692 00:34:27,052 --> 00:34:29,260 And the last thing I'm doing down here is overwriting 693 00:34:29,260 --> 00:34:31,449 the __str__ method. 694 00:34:31,449 --> 00:34:33,880 So let's look at the code. 695 00:34:33,880 --> 00:34:41,620 I'm going to comment this part out, and uncomment the student, 696 00:34:41,620 --> 00:34:42,992 and see what we get. 697 00:34:45,760 --> 00:34:49,270 OK, so here, I am creating the student. 698 00:34:49,270 --> 00:34:52,530 I'm creating one student whose major is CS, name is Alice, 699 00:34:52,530 --> 00:34:54,210 and age is 20. 700 00:34:54,210 --> 00:34:56,770 s2 is going to be another student-- name-- 701 00:34:56,770 --> 00:34:57,997 Beth, age-- 18. 702 00:34:57,997 --> 00:34:59,830 And the major is going to be None, because I 703 00:34:59,830 --> 00:35:02,090 didn't pass in any major here. 704 00:35:02,090 --> 00:35:04,150 So by default, using the default argument, 705 00:35:04,150 --> 00:35:05,290 it's going to be None. 706 00:35:05,290 --> 00:35:08,590 If I print s1, s2, that's going to print out these two things 707 00:35:08,590 --> 00:35:12,270 over here just by whatever __str__ method does. 708 00:35:14,780 --> 00:35:19,020 And then I'm going to get the students to speak. 709 00:35:19,020 --> 00:35:20,780 And if I run it multiple times, you 710 00:35:20,780 --> 00:35:23,670 can see that it's going to print different things each time. 711 00:35:26,670 --> 00:35:29,160 So "I need sleep," "I have homework," "I need sleep," 712 00:35:29,160 --> 00:35:31,570 "I have homework," yeah. 713 00:35:31,570 --> 00:35:33,904 So every time, it's going to print something different. 714 00:35:37,800 --> 00:35:43,180 OK, questions about inheritance in this example? 715 00:35:46,512 --> 00:35:47,837 OK. 716 00:35:47,837 --> 00:35:49,920 Last thing we're going to talk about in this class 717 00:35:49,920 --> 00:35:52,200 is an idea of-- or in this lecture, 718 00:35:52,200 --> 00:35:55,320 is the idea of-- a class variable, OK? 719 00:35:55,320 --> 00:35:58,320 So to illustrate this, I'm going to create yet another subclass 720 00:35:58,320 --> 00:36:00,350 of my animal called a rabbit. 721 00:36:03,970 --> 00:36:08,530 So class variables-- so so far, we've seen-- sorry, 722 00:36:08,530 --> 00:36:09,250 let me back up. 723 00:36:09,250 --> 00:36:12,640 So so far, we've seen instance variables, right? 724 00:36:12,640 --> 00:36:15,776 So things like self.name, self.age, those 725 00:36:15,776 --> 00:36:16,900 are all instance variables. 726 00:36:16,900 --> 00:36:18,880 So they're variables that are specif-- 727 00:36:18,880 --> 00:36:22,190 they are common across all of the instances of the class, 728 00:36:22,190 --> 00:36:22,690 right? 729 00:36:22,690 --> 00:36:26,290 Every instance of the class has this particular variable. 730 00:36:26,290 --> 00:36:27,890 But the value of the variable is going 731 00:36:27,890 --> 00:36:31,800 to be different between all of the different instances. 732 00:36:31,800 --> 00:36:36,560 So class variables are going to be variables 733 00:36:36,560 --> 00:36:38,330 whose values are shared between all 734 00:36:38,330 --> 00:36:40,130 of the instances in the class. 735 00:36:40,130 --> 00:36:46,435 So if one instance of the class modifies this class variable, 736 00:36:46,435 --> 00:36:48,610 then, any other instance of the class 737 00:36:48,610 --> 00:36:50,270 is going to see the modified value. 738 00:36:50,270 --> 00:36:55,020 So it's sort of shared among all of the different instances. 739 00:36:55,020 --> 00:36:56,970 So we're going to use class variables 740 00:36:56,970 --> 00:36:58,325 to keep track of rabbits. 741 00:37:00,940 --> 00:37:04,160 OK, so we're creating this class, Rabbit. 742 00:37:04,160 --> 00:37:05,040 tag = 1. 743 00:37:05,040 --> 00:37:08,970 We haven't seen something like this before. 744 00:37:08,970 --> 00:37:11,990 So tag is our class variable. 745 00:37:11,990 --> 00:37:15,380 Class variables are typically defined inside the class 746 00:37:15,380 --> 00:37:21,000 definition but outside of the __init__. 747 00:37:21,000 --> 00:37:22,710 So tag is going to be a class variable, 748 00:37:22,710 --> 00:37:26,420 and I'm initializing it to 1. 749 00:37:26,420 --> 00:37:29,450 Inside the __init__, this tells us how to create a Rabbit 750 00:37:29,450 --> 00:37:30,170 object. 751 00:37:30,170 --> 00:37:32,990 So I'm going to give it self as usual, an age, and then 752 00:37:32,990 --> 00:37:34,550 two parents. 753 00:37:34,550 --> 00:37:38,000 Don't worry about the two parents for now. 754 00:37:38,000 --> 00:37:41,000 Inside the __init__-- sorry, inside the __init__-- 755 00:37:41,000 --> 00:37:45,440 I'm going to call the __init__ of the animal just to do less 756 00:37:45,440 --> 00:37:47,320 work. 757 00:37:47,320 --> 00:37:49,930 Python already knows how to initialize an animal for me, 758 00:37:49,930 --> 00:37:50,860 so let's do that. 759 00:37:50,860 --> 00:37:54,920 So that's going to set the two data attributes, name and age. 760 00:37:54,920 --> 00:37:56,420 I'm going to set the data attributes 761 00:37:56,420 --> 00:37:58,160 for parent1, parent2 for a rabbit 762 00:37:58,160 --> 00:38:00,145 to be whatever's passed in. 763 00:38:00,145 --> 00:38:01,520 And then, this is where I'm going 764 00:38:01,520 --> 00:38:04,220 to use this class variable. 765 00:38:04,220 --> 00:38:09,090 So I'm creating this data attribute 766 00:38:09,090 --> 00:38:13,380 instance variable particular to a specific instance called 767 00:38:13,380 --> 00:38:15,730 rid, OK? 768 00:38:15,730 --> 00:38:20,890 And I'm assigning this instance variable to the class variable. 769 00:38:20,890 --> 00:38:23,590 And I access class variables using not self, 770 00:38:23,590 --> 00:38:26,755 but the class name-- so in this case, rabbit.tag. 771 00:38:30,010 --> 00:38:32,290 So initially, tag is going to be 1. 772 00:38:32,290 --> 00:38:37,116 And then, the __init__ is going to increment the tag by 1 here, 773 00:38:37,116 --> 00:38:37,960 OK? 774 00:38:37,960 --> 00:38:39,910 So that means that, from now on, if I 775 00:38:39,910 --> 00:38:42,130 create any other instances, the other instances 776 00:38:42,130 --> 00:38:45,070 are going to be accessing the updated value of tag instead 777 00:38:45,070 --> 00:38:46,450 of being 1. 778 00:38:46,450 --> 00:38:50,060 So let's do a quick drawing to show you what I mean. 779 00:38:50,060 --> 00:38:57,224 So let's say I have Rabbit.tag here, OK? 780 00:39:00,360 --> 00:39:05,620 So initially, tag is going to be 1, OK? 781 00:39:05,620 --> 00:39:08,090 And then I'm going to create a new Rabbit object. 782 00:39:08,090 --> 00:39:10,550 So this is as I'm calling the code, OK? 783 00:39:10,550 --> 00:39:15,290 So let's say this is a rabbit object-- oh boy, OK-- r1. 784 00:39:17,777 --> 00:39:19,860 You know, I actually googled how to draw a rabbit, 785 00:39:19,860 --> 00:39:21,090 but that didn't help at all. 786 00:39:21,090 --> 00:39:28,620 OK, so r1 is going to be a new rabbit that we create. 787 00:39:28,620 --> 00:39:33,270 Initially, what happens is, when I first create this new rabbit, 788 00:39:33,270 --> 00:39:38,770 it's going to access the class variable, which, 789 00:39:38,770 --> 00:39:41,210 it's current value is 1. 790 00:39:41,210 --> 00:39:45,340 So when I create the rabbit ID-- the rabbit ID, 791 00:39:45,340 --> 00:39:50,345 r1.rid-- this is going to get the value 1. 792 00:39:53,200 --> 00:39:55,390 And according to the code, after I 793 00:39:55,390 --> 00:39:57,160 set the rabbit ID to whatever tag is, 794 00:39:57,160 --> 00:39:59,660 I'm going to increment the tag. 795 00:39:59,660 --> 00:40:02,230 So this is going to say, OK, now that I've said it, 796 00:40:02,230 --> 00:40:07,000 I'm going to go back up here and increment the tag to be 2. 797 00:40:07,000 --> 00:40:07,970 OK. 798 00:40:07,970 --> 00:40:11,612 So let's say I create another Rabbit object, OK? 799 00:40:11,612 --> 00:40:18,180 All right, there-- that's a sad rabbit, r2. 800 00:40:18,180 --> 00:40:24,430 The ID of r2 is going to be what? 801 00:40:24,430 --> 00:40:28,150 Well, according to the way we create a new Rabbit object 802 00:40:28,150 --> 00:40:30,910 is it's going to access whatever the value of tag 803 00:40:30,910 --> 00:40:33,430 is, which is a class variable. 804 00:40:33,430 --> 00:40:36,400 It was changed by the previous creation of my rabbit, 805 00:40:36,400 --> 00:40:39,010 so now I'm going to access that, right? 806 00:40:39,010 --> 00:40:40,792 So the value is going to be 2. 807 00:40:43,322 --> 00:40:45,030 And according to the code, the next thing 808 00:40:45,030 --> 00:40:48,630 I do after I create the instance rid 809 00:40:48,630 --> 00:40:50,850 is I'm going to increment tag. 810 00:40:50,850 --> 00:40:56,560 So I'm incrementing the class variable to be 3, OK? 811 00:40:56,560 --> 00:40:57,990 So notice that all of my instances 812 00:40:57,990 --> 00:41:02,790 are accessing this shared resource, 813 00:41:02,790 --> 00:41:05,580 this shared variable called tag. 814 00:41:05,580 --> 00:41:07,530 So as I'm creating more and more rabbits, 815 00:41:07,530 --> 00:41:09,870 they're all going to be incrementing the value of tag, 816 00:41:09,870 --> 00:41:13,480 because it's shared among all of the instances. 817 00:41:13,480 --> 00:41:17,470 And so this value, this tag class variable, 818 00:41:17,470 --> 00:41:20,830 keeps track of how many different instances of a rab-- 819 00:41:20,830 --> 00:41:23,110 of how many different instances of rabbits 820 00:41:23,110 --> 00:41:27,390 I've created throughout my entire program, OK? 821 00:41:27,390 --> 00:41:30,260 So the big idea here is that class variables are shared 822 00:41:30,260 --> 00:41:31,790 across all the instances. 823 00:41:31,790 --> 00:41:34,590 So they can all modify them. 824 00:41:34,590 --> 00:41:40,850 But these rids, right, these instance variables, 825 00:41:40,850 --> 00:41:43,950 are only for that particular instance. 826 00:41:43,950 --> 00:41:49,850 So r2 can't have access to r1's ID value, nor could change it. 827 00:41:49,850 --> 00:41:54,702 But it won't change it across all of the different instances, 828 00:41:54,702 --> 00:41:55,202 OK? 829 00:42:00,840 --> 00:42:07,060 So that's how the __init__ method works of Rabbit, OK? 830 00:42:07,060 --> 00:42:09,690 So we have these tags that keep track of how many rabbits 831 00:42:09,690 --> 00:42:11,490 we've created. 832 00:42:11,490 --> 00:42:14,597 We have a couple of getter-- we have some getters here 833 00:42:14,597 --> 00:42:15,555 to get all the parents. 834 00:42:15,555 --> 00:42:20,020 So now let's add a somewhat more interesting function. 835 00:42:20,020 --> 00:42:23,230 Oh, I just want to mention, when I'm getting the rid, 836 00:42:23,230 --> 00:42:26,520 I'm actually using this cool zfill() function here, 837 00:42:26,520 --> 00:42:30,850 or method, which actually pads the beginning of any number 838 00:42:30,850 --> 00:42:34,180 with however many zeros in order to get to that number here. 839 00:42:34,180 --> 00:42:36,530 So the number 1 becomes 001 and so on. 840 00:42:36,530 --> 00:42:40,510 So it ensures that I have this nice-looking ID type 841 00:42:40,510 --> 00:42:42,160 thing that's always three digits long. 842 00:42:44,880 --> 00:42:47,120 So let's try to work with this Rabbit object. 843 00:42:47,120 --> 00:42:50,830 Let's define what happens when you add two rabbits together, 844 00:42:50,830 --> 00:42:53,730 OK-- in this class, not in the real world. 845 00:42:53,730 --> 00:42:54,850 OK. 846 00:42:54,850 --> 00:42:59,760 So if I want to use the plus operator between two rabbit 847 00:42:59,760 --> 00:43:07,750 instances, I have to implement this __add__ method, OK? 848 00:43:07,750 --> 00:43:11,574 So all I'm doing here is I'm returning a new Rabbit object, 849 00:43:11,574 --> 00:43:12,400 OK? 850 00:43:12,400 --> 00:43:14,290 Whoops, sorry about that. 851 00:43:14,290 --> 00:43:18,310 And let's recall the __init__ method of the rabbit, OK? 852 00:43:18,310 --> 00:43:20,394 So when I'm returning a new Rabbit object, 853 00:43:20,394 --> 00:43:22,060 I'm returning a new Rabbit object that's 854 00:43:22,060 --> 00:43:25,090 going to have an age of 0. 855 00:43:25,090 --> 00:43:28,180 Self-- so the Rabbit object I'm calling this method on 856 00:43:28,180 --> 00:43:31,540 is going to be the parent of the new rabbit. 857 00:43:31,540 --> 00:43:36,066 And other is going to be the other parent of the new rabbit, 858 00:43:36,066 --> 00:43:38,330 OK? 859 00:43:38,330 --> 00:43:58,950 So if we look at the code, and I run it, 860 00:43:58,950 --> 00:44:04,710 this part here, I'm creating three rabbits, r1, r2, and r3. 861 00:44:04,710 --> 00:44:08,220 Notice this class variable is working 862 00:44:08,220 --> 00:44:10,680 as expected, because the IDs of each of my rabbits 863 00:44:10,680 --> 00:44:12,240 increments as I create more rabbits. 864 00:44:12,240 --> 00:44:17,710 So we have 001, 002, 003. 865 00:44:17,710 --> 00:44:20,500 If I print r1, and r2, and r3-- that 866 00:44:20,500 --> 00:44:23,800 was these three lines over here-- the parents of r1 and r2 867 00:44:23,800 --> 00:44:29,260 are None, because that's just the default-- yes, the default 868 00:44:29,260 --> 00:44:31,950 arguments for creating a rabbit. 869 00:44:31,950 --> 00:44:34,300 To add two rabbits together, I use the plus operator 870 00:44:34,300 --> 00:44:37,460 between two Rabbit objects. 871 00:44:37,460 --> 00:44:40,640 And on the right here, I'm testing rabbit addition. 872 00:44:40,640 --> 00:44:44,815 And I can print out the IDs of all my rabbits. 873 00:44:44,815 --> 00:44:46,940 And notice that, when I've created this new rabbit, 874 00:44:46,940 --> 00:44:50,360 r4, the ID of it still kept incrementing. 875 00:44:50,360 --> 00:44:55,670 So now, the ID of the fourth rabbit is 004. 876 00:44:55,670 --> 00:44:57,590 And then, when I get r4's parents, 877 00:44:57,590 --> 00:45:00,295 they are as we want them to be, so r1 and r2. 878 00:45:05,530 --> 00:45:09,251 The other thing I want to do is to compare two rabbits. 879 00:45:09,251 --> 00:45:10,750 So if I want to compare two rabbits, 880 00:45:10,750 --> 00:45:13,370 I want to make sure that their parents are the same. 881 00:45:13,370 --> 00:45:17,421 So I can compare the first parent of the first rabbit 882 00:45:17,421 --> 00:45:19,170 with the first parent of the second rabbit 883 00:45:19,170 --> 00:45:21,430 and the second parent of the first rabbit 884 00:45:21,430 --> 00:45:23,830 to the second parent of second rabbit 885 00:45:23,830 --> 00:45:26,650 or getting the combinations of those two. 886 00:45:26,650 --> 00:45:29,470 So that's what these two Booleans are doing. 887 00:45:29,470 --> 00:45:31,600 So these are going to tell me-- these 888 00:45:31,600 --> 00:45:34,480 are going to be Boolean values, either True or False. 889 00:45:34,480 --> 00:45:36,910 And I'm going to return either they 890 00:45:36,910 --> 00:45:38,860 have the same parents of that type 891 00:45:38,860 --> 00:45:41,956 or the same parents criss-crossed, OK? 892 00:45:41,956 --> 00:45:43,330 So here, notice that I'm actually 893 00:45:43,330 --> 00:45:46,840 comparing the IDs of the rabbits as opposed to the Rabbit 894 00:45:46,840 --> 00:45:49,220 objects directly, OK? 895 00:45:49,220 --> 00:45:53,530 So if, instead of comparing the IDs in here, 896 00:45:53,530 --> 00:45:56,490 I was comparing the parents themselves, directly, 897 00:45:56,490 --> 00:45:59,800 what would end up happening is this function, this method, 898 00:45:59,800 --> 00:46:02,770 eq(), would get called over and over again. 899 00:46:02,770 --> 00:46:05,830 Because here, we have parents that are rabbits. 900 00:46:05,830 --> 00:46:08,890 And at some point, the parents of the very, very first rabbits 901 00:46:08,890 --> 00:46:11,690 ever created by this program are None. 902 00:46:11,690 --> 00:46:14,410 And so when I try to call-- when I 903 00:46:14,410 --> 00:46:19,330 try to call the parent one of None, that's going to give me 904 00:46:19,330 --> 00:46:21,730 an error, OK, something like an attribute error 905 00:46:21,730 --> 00:46:25,780 where None doesn't have this parent attribute, OK? 906 00:46:25,780 --> 00:46:28,240 So that's why I'm comparing IDs here, OK? 907 00:46:28,240 --> 00:46:32,140 And the code in the lecture here shows 908 00:46:32,140 --> 00:46:36,910 you some tests about whether rabbits have the same parents. 909 00:46:36,910 --> 00:46:38,470 And I've created new rabbits here, 910 00:46:38,470 --> 00:46:43,490 r3 and r4, the addition of those two. 911 00:46:43,490 --> 00:46:47,180 And r5 and r6 are going to have the same parents down here-- 912 00:46:47,180 --> 00:46:51,710 True-- but r4 and r6 don't, OK? 913 00:46:51,710 --> 00:46:54,290 So just to wrap it up, object-oriented programming 914 00:46:54,290 --> 00:46:57,000 is the idea of creating your own collections of data 915 00:46:57,000 --> 00:46:59,000 where you can organize the information in a very 916 00:46:59,000 --> 00:46:59,810 consistent manner. 917 00:46:59,810 --> 00:47:01,910 So every single type of object that you 918 00:47:01,910 --> 00:47:05,270 create of this particular type that you create-- sorry, 919 00:47:05,270 --> 00:47:08,030 every object instance of a particular type 920 00:47:08,030 --> 00:47:10,250 is going to have the exact same data attributes 921 00:47:10,250 --> 00:47:11,870 and the exact same methods, OK? 922 00:47:11,870 --> 00:47:15,050 So this really comes back to the idea of decomposition 923 00:47:15,050 --> 00:47:16,880 and abstraction in programming. 924 00:47:16,880 --> 00:47:19,450 All right, thanks, everyone.