1 00:00:00,000 --> 00:00:00,984 2 00:00:00,984 --> 00:00:17,787 [MUSIC PLAYING] 3 00:00:17,787 --> 00:00:19,620 BRIAN YU: All right, welcome back, everyone, 4 00:00:19,620 --> 00:00:21,930 to Web Programming with Python and JavaScript. 5 00:00:21,930 --> 00:00:24,690 And today, we take a look at one of the two main languages we're 6 00:00:24,690 --> 00:00:26,310 going to be looking at in this course. 7 00:00:26,310 --> 00:00:28,710 In particular, we're going to be looking at Python. 8 00:00:28,710 --> 00:00:30,870 Python is a very powerful language that makes 9 00:00:30,870 --> 00:00:33,438 it very easy to build applications quickly 10 00:00:33,438 --> 00:00:36,480 because there are a lot of features that are built into the language that 11 00:00:36,480 --> 00:00:39,420 just make it convenient for quick and productive development. 12 00:00:39,420 --> 00:00:42,990 So one of the goals of today is to introduce you to the Python programming 13 00:00:42,990 --> 00:00:44,860 language if you haven't seen it before. 14 00:00:44,860 --> 00:00:46,980 And even if you have seen it before, to give you 15 00:00:46,980 --> 00:00:49,578 a taste for what the language has to offer, exploring some 16 00:00:49,578 --> 00:00:51,870 of the more advanced features in some of the techniques 17 00:00:51,870 --> 00:00:55,410 we can use using Python to be able to develop applications 18 00:00:55,410 --> 00:00:57,030 all the more effectively. 19 00:00:57,030 --> 00:01:00,480 So we begin with our very first Python program, just a program 20 00:01:00,480 --> 00:01:01,800 that says, "hello, world." 21 00:01:01,800 --> 00:01:03,810 We're going to be writing it in a text file. 22 00:01:03,810 --> 00:01:07,140 And the program just looks like a single line, just like this. 23 00:01:07,140 --> 00:01:09,450 And if you've used other programming languages before, 24 00:01:09,450 --> 00:01:12,060 like C, or Java, or other languages, this probably 25 00:01:12,060 --> 00:01:14,290 looks pretty familiar syntax-wise. 26 00:01:14,290 --> 00:01:16,260 But just to break it down, we have a function 27 00:01:16,260 --> 00:01:19,740 called Print built into the Python programming language for us. 28 00:01:19,740 --> 00:01:23,250 And like many other programming languages, functions in Python 29 00:01:23,250 --> 00:01:25,680 take their arguments inside of parentheses. 30 00:01:25,680 --> 00:01:29,280 So inside of these parentheses are the argument, or the input, 31 00:01:29,280 --> 00:01:32,280 to the Print function, which in this case is just the words, 32 00:01:32,280 --> 00:01:35,740 "hello, world" followed by an exclamation point. 33 00:01:35,740 --> 00:01:38,760 So here's how we can actually take this program and run it. 34 00:01:38,760 --> 00:01:40,770 I'm going to go into my text editor and create 35 00:01:40,770 --> 00:01:44,820 a new file that I'll call hello.py. 36 00:01:44,820 --> 00:01:49,830 dot-py or dot-py is the conventional extension for Python programs. 37 00:01:49,830 --> 00:01:53,880 So I create a file called hello.pi inside of which will just be the Python 38 00:01:53,880 --> 00:01:56,070 code that we just saw a moment ago. 39 00:01:56,070 --> 00:01:57,700 We'll call the Print function. 40 00:01:57,700 --> 00:02:00,570 And as an argument, or the input, to the Print function, 41 00:02:00,570 --> 00:02:05,360 I'll say, "hello, world" exclamation point. 42 00:02:05,360 --> 00:02:09,770 Now in order to run this program, we're going to use a program in our terminal 43 00:02:09,770 --> 00:02:12,680 that also just so happens to be called Python. 44 00:02:12,680 --> 00:02:15,380 Python is what you might call an interpreted language, 45 00:02:15,380 --> 00:02:17,900 meaning we're going to run a program called Python, 46 00:02:17,900 --> 00:02:22,070 which is an interpreter that is going to read our .py file line by line, 47 00:02:22,070 --> 00:02:25,640 executing each line and interpreting what it is that it means in a way that 48 00:02:25,640 --> 00:02:27,710 the computer can actually understand. 49 00:02:27,710 --> 00:02:30,320 So we'll run Python followed by the name of the program 50 00:02:30,320 --> 00:02:33,480 that we'd like to interpret, in this case hello.py. 51 00:02:33,480 --> 00:02:36,710 And when we run this program, we see that the words "hello, world" 52 00:02:36,710 --> 00:02:38,120 are printed to the terminal. 53 00:02:38,120 --> 00:02:38,970 And that's it. 54 00:02:38,970 --> 00:02:40,220 That's the end of the program. 55 00:02:40,220 --> 00:02:42,530 And that's the very first program that we've written 56 00:02:42,530 --> 00:02:44,780 using the Python programming language. 57 00:02:44,780 --> 00:02:47,240 So now already we've seen a couple of features of Python. 58 00:02:47,240 --> 00:02:49,160 The ability to interpret Python-- there's 59 00:02:49,160 --> 00:02:53,150 no need to compile it into a binary first in order to run a Python program. 60 00:02:53,150 --> 00:02:54,350 We've seen functions. 61 00:02:54,350 --> 00:02:58,730 And we've also seen strings, just text that we can provide in quotation marks 62 00:02:58,730 --> 00:03:02,930 that we can provide as input to other functions or manipulate in other ways. 63 00:03:02,930 --> 00:03:07,130 And we'll see some examples of a string manipulation a little bit later. 64 00:03:07,130 --> 00:03:11,150 Like many other programming languages, Python also supports variables. 65 00:03:11,150 --> 00:03:13,700 And in order to assign a new value to a variable, 66 00:03:13,700 --> 00:03:15,870 the syntax looks a little something like this. 67 00:03:15,870 --> 00:03:19,160 If I have a line like a equals 28, what that's going to mean 68 00:03:19,160 --> 00:03:22,880 is take the value 28 and assign it, store it inside 69 00:03:22,880 --> 00:03:25,130 of this variable called a. 70 00:03:25,130 --> 00:03:27,448 Now, unlike other languages like C or Java 71 00:03:27,448 --> 00:03:29,240 which you might be familiar with, where you 72 00:03:29,240 --> 00:03:31,250 have to specify the type of every variable 73 00:03:31,250 --> 00:03:35,210 you create-- you have to say, like, int a to mean a is an integer. 74 00:03:35,210 --> 00:03:38,360 Python doesn't require you to tell you what the types of each 75 00:03:38,360 --> 00:03:40,400 of these variables actually are. 76 00:03:40,400 --> 00:03:42,620 So we can just say a equals 28 and Python 77 00:03:42,620 --> 00:03:45,350 knows that because this number is an int, that it's 78 00:03:45,350 --> 00:03:49,130 going to represent the variable a as an int, that it knows, 79 00:03:49,130 --> 00:03:53,900 it's able to infer, what the types of any these values happen to be. 80 00:03:53,900 --> 00:03:56,180 So all the values do indeed have types. 81 00:03:56,180 --> 00:03:58,650 You just don't explicitly need to state them. 82 00:03:58,650 --> 00:04:01,400 So for example, this here, the number 28, is a type int. 83 00:04:01,400 --> 00:04:02,390 It's an integer. 84 00:04:02,390 --> 00:04:04,880 A number like 1.5 has a decimal in it. 85 00:04:04,880 --> 00:04:06,440 It's a floating point number. 86 00:04:06,440 --> 00:04:09,440 So that, in Python, is what we might call a float type. 87 00:04:09,440 --> 00:04:11,450 Any type of text, something like the word 88 00:04:11,450 --> 00:04:14,580 "hello" wrapped in either double quotation marks or single quotation 89 00:04:14,580 --> 00:04:15,080 marks-- 90 00:04:15,080 --> 00:04:19,910 Python supports both-- is what we would call the str type, short for string. 91 00:04:19,910 --> 00:04:21,890 We also have a type for Boolean values, things 92 00:04:21,890 --> 00:04:24,350 that can be either true or false. 93 00:04:24,350 --> 00:04:28,940 In Python, those are represented using a capital T, true, and a capital F, 94 00:04:28,940 --> 00:04:29,850 false. 95 00:04:29,850 --> 00:04:31,490 Those are of type bool. 96 00:04:31,490 --> 00:04:33,800 And also, we have a special type in Python 97 00:04:33,800 --> 00:04:38,720 called the none type, which only has one possible value, this capital N, none. 98 00:04:38,720 --> 00:04:41,030 And none as a value we'll use whenever we 99 00:04:41,030 --> 00:04:43,790 want to represent the lack of a value somewhere. 100 00:04:43,790 --> 00:04:46,490 So if we have a function that is not returning anything, 101 00:04:46,490 --> 00:04:48,950 it is really returning none, effectively. 102 00:04:48,950 --> 00:04:51,140 And so you might imagine that none can be useful 103 00:04:51,140 --> 00:04:55,282 if ever you want a variable to represent the absence of something, for example. 104 00:04:55,282 --> 00:04:58,490 So lots of different possible types, and there are more types than just this. 105 00:04:58,490 --> 00:05:01,940 But here's a sampling of the possible variables and types that 106 00:05:01,940 --> 00:05:04,820 might exist inside of this language. 107 00:05:04,820 --> 00:05:07,670 So now let's try and actually use a variable 108 00:05:07,670 --> 00:05:11,270 in order to do something a little bit more interesting inside of our program. 109 00:05:11,270 --> 00:05:14,780 And we'll write a program that's able to take input from the user 110 00:05:14,780 --> 00:05:17,540 in order to say hello to them, for example. 111 00:05:17,540 --> 00:05:19,620 So I'll create a new file. 112 00:05:19,620 --> 00:05:22,274 We'll call it name.py. 113 00:05:22,274 --> 00:05:25,200 And to start, I'd like to prompt the user for input. 114 00:05:25,200 --> 00:05:29,590 I'd like to prompt the user to, for example, type in their name. 115 00:05:29,590 --> 00:05:30,820 So how might we do that? 116 00:05:30,820 --> 00:05:33,090 Well, just as there is a Print function that 117 00:05:33,090 --> 00:05:36,690 is built into Python that just prints out whatever the argument happens 118 00:05:36,690 --> 00:05:39,510 to be, Python also has a built in function 119 00:05:39,510 --> 00:05:42,690 called Input that prompts the user for input and asks them just 120 00:05:42,690 --> 00:05:44,470 type in some input. 121 00:05:44,470 --> 00:05:48,810 So let's provide some input and ask the user to type in their name, 122 00:05:48,810 --> 00:05:50,380 for example. 123 00:05:50,380 --> 00:05:52,860 And then we can save the result, the output 124 00:05:52,860 --> 00:05:55,085 of that function inside of a variable. 125 00:05:55,085 --> 00:05:57,960 And in this case, I'll save it inside of a variable that in this case 126 00:05:57,960 --> 00:06:01,030 also just happens to be called Name. 127 00:06:01,030 --> 00:06:02,500 Now we can run the program. 128 00:06:02,500 --> 00:06:07,740 I can run the program by going into my terminal and typing Python name.py. 129 00:06:07,740 --> 00:06:08,560 I'll press Return. 130 00:06:08,560 --> 00:06:11,230 And we'll see the program prompts me to type in my name. 131 00:06:11,230 --> 00:06:15,490 I see name colon space, which is that string I provided as the argument 132 00:06:15,490 --> 00:06:16,960 to the input function. 133 00:06:16,960 --> 00:06:19,960 And this now prompts me to type in my name, so I will. 134 00:06:19,960 --> 00:06:23,120 And after that, nothing seems to happen so far. 135 00:06:23,120 --> 00:06:25,120 So now I'd like to do something with that input. 136 00:06:25,120 --> 00:06:26,200 I typed in my name. 137 00:06:26,200 --> 00:06:29,820 I'd like to say, like, hello, for example to myself. 138 00:06:29,820 --> 00:06:31,630 So I'll go back into this program. 139 00:06:31,630 --> 00:06:36,640 And now what I can do is I can say print hello comma. 140 00:06:36,640 --> 00:06:39,820 And then I can say plus name. 141 00:06:39,820 --> 00:06:42,620 This plus operator in Python does a number of different things. 142 00:06:42,620 --> 00:06:45,290 If I have two numbers, it'll add those two numbers together. 143 00:06:45,290 --> 00:06:49,180 But with two strings, plus can actually concatenate, or combine, 144 00:06:49,180 --> 00:06:50,600 two strings together. 145 00:06:50,600 --> 00:06:54,610 So I can combine hello comma space with whatever the value of name 146 00:06:54,610 --> 00:06:56,290 happens to be. 147 00:06:56,290 --> 00:06:58,510 So now I'll rerun this program. 148 00:06:58,510 --> 00:07:01,492 Python name.py. 149 00:07:01,492 --> 00:07:03,270 Type in my name. 150 00:07:03,270 --> 00:07:07,800 And now we see "hello, Brian" as the output of the program. 151 00:07:07,800 --> 00:07:11,960 So this is one way that you can manipulate strings in Python. 152 00:07:11,960 --> 00:07:15,230 Another way that's quite popular in later versions of Python 3 153 00:07:15,230 --> 00:07:19,090 is a method known as using f strings, short for formatted strings. 154 00:07:19,090 --> 00:07:21,260 And in order to use f strings in Python, it's 155 00:07:21,260 --> 00:07:24,230 going to be a similar but slightly different syntax. 156 00:07:24,230 --> 00:07:27,770 Instead of just having a string in double quotation marks, 157 00:07:27,770 --> 00:07:31,010 we'll put the letter f before the string. 158 00:07:31,010 --> 00:07:34,730 And inside of the string, I can now say hello comma-- 159 00:07:34,730 --> 00:07:36,650 and then if in a formatted string, if I want 160 00:07:36,650 --> 00:07:39,620 to plug in the value of a variable, I can do so 161 00:07:39,620 --> 00:07:42,270 by specifying it in curly braces. 162 00:07:42,270 --> 00:07:47,360 So what I'll say here is, inside of curly braces, name. 163 00:07:47,360 --> 00:07:50,720 And so what's going on here is I am telling this formatted string 164 00:07:50,720 --> 00:07:54,060 to substitute right here the value of a variable. 165 00:07:54,060 --> 00:07:56,400 So I prompted the user for input to type in their name. 166 00:07:56,400 --> 00:08:00,620 We took their name, saved it inside of this variable called name. 167 00:08:00,620 --> 00:08:03,080 And now here in this print statement on line two, 168 00:08:03,080 --> 00:08:06,920 I'm printing out a formatted string that is hello comma. 169 00:08:06,920 --> 00:08:09,530 And then in curly braces here, I'm saying plug 170 00:08:09,530 --> 00:08:12,078 in the value of the variable name. 171 00:08:12,078 --> 00:08:14,870 And so that is going to have the effect of taking whatever name was 172 00:08:14,870 --> 00:08:17,240 provided as input and printing it out. 173 00:08:17,240 --> 00:08:19,340 And this is a slightly more efficient way 174 00:08:19,340 --> 00:08:22,160 of being able to quickly create strings by plugging 175 00:08:22,160 --> 00:08:24,370 in values into those strings. 176 00:08:24,370 --> 00:08:29,620 So now I'll see the exact same behavior if I run Python name.py 177 00:08:29,620 --> 00:08:31,830 and prompt it to type in my name. 178 00:08:31,830 --> 00:08:32,960 I'm like, Brian. 179 00:08:32,960 --> 00:08:35,812 And then I see the result, "hello, Brian" for example. 180 00:08:35,812 --> 00:08:37,520 And so those are a couple of ways that we 181 00:08:37,520 --> 00:08:41,210 can deal with strings, manipulating strings, and combining strings 182 00:08:41,210 --> 00:08:44,310 using this technique. 183 00:08:44,310 --> 00:08:47,720 So in addition to variables, Python also supports all of the same other features 184 00:08:47,720 --> 00:08:50,390 that are core to many procedural programming languages, 185 00:08:50,390 --> 00:08:52,650 such as conditions, for example. 186 00:08:52,650 --> 00:08:57,290 So let's take a look at an example now of seeing whether a number is positive, 187 00:08:57,290 --> 00:09:00,500 or negative, or zero, for example. 188 00:09:00,500 --> 00:09:04,580 So I'll create a new file that I'll call conditions.py. 189 00:09:04,580 --> 00:09:09,270 And inside of conditions.py, I'll first prompt the user to type in some input. 190 00:09:09,270 --> 00:09:14,310 I'll say input number to mean type in a number. 191 00:09:14,310 --> 00:09:19,700 And we'll save that input inside of a variable that I'm just going to call n. 192 00:09:19,700 --> 00:09:21,620 And now I can ask questions. 193 00:09:21,620 --> 00:09:26,000 I can say something like if n is greater than zero. 194 00:09:26,000 --> 00:09:30,580 Then print n is positive. 195 00:09:30,580 --> 00:09:33,480 And so what's going on here is I have a Python condition. 196 00:09:33,480 --> 00:09:35,400 And the way a Python condition works is it 197 00:09:35,400 --> 00:09:39,930 begins with this keyword, a keyword like if, followed by a Boolean 198 00:09:39,930 --> 00:09:43,320 expression, some expression that's going to evaluate to true, or false, 199 00:09:43,320 --> 00:09:45,270 or something kind of like true or false. 200 00:09:45,270 --> 00:09:48,060 We can be a little bit loose about that, as we may see later. 201 00:09:48,060 --> 00:09:51,240 And then a colon means, all right, here is the beginning 202 00:09:51,240 --> 00:09:53,280 of the body of the if statement. 203 00:09:53,280 --> 00:09:55,140 And in Python, the way we know that we're 204 00:09:55,140 --> 00:09:58,380 inside the body of an if statement or inside the body of any other block 205 00:09:58,380 --> 00:10:00,760 of code is via indentation. 206 00:10:00,760 --> 00:10:03,990 So in some languages, like C, or in languages like HTML, 207 00:10:03,990 --> 00:10:07,470 which we saw a couple of lectures ago, the indentation 208 00:10:07,470 --> 00:10:11,250 isn't strictly required by the computer to be able to parse and understand 209 00:10:11,250 --> 00:10:12,540 what's inside the program. 210 00:10:12,540 --> 00:10:14,130 In Python, it's different. 211 00:10:14,130 --> 00:10:17,370 The indentation is required because the indentation 212 00:10:17,370 --> 00:10:21,360 is how the program knows what code is inside of the if statement 213 00:10:21,360 --> 00:10:24,610 and what code is outside of the if statement. 214 00:10:24,610 --> 00:10:26,580 So we have if n is greater than zero colon. 215 00:10:26,580 --> 00:10:29,340 And then everything indented underneath the if, 216 00:10:29,340 --> 00:10:31,390 is all of the body of the if statement. 217 00:10:31,390 --> 00:10:33,420 It is the lines of code that will execute 218 00:10:33,420 --> 00:10:37,260 if this condition, this Boolean expression and greater than zero, 219 00:10:37,260 --> 00:10:38,650 happens to be true. 220 00:10:38,650 --> 00:10:42,900 So if end is greater than zero, will print out n is positive. 221 00:10:42,900 --> 00:10:45,810 And then we can add an additional condition. 222 00:10:45,810 --> 00:10:47,680 I can say something like-- 223 00:10:47,680 --> 00:10:52,757 well, I could say something like else print n is not positive. 224 00:10:52,757 --> 00:10:54,840 But I can be a little bit more specific than that. 225 00:10:54,840 --> 00:10:56,400 Here is a sort of two branches. 226 00:10:56,400 --> 00:10:59,400 One if n is greater than 0, and one else case 227 00:10:59,400 --> 00:11:02,070 to handle all of the other possible scenarios. 228 00:11:02,070 --> 00:11:05,220 But really, what I'd like to do is perform a second check. 229 00:11:05,220 --> 00:11:07,590 In other languages, this might be called an else-if. 230 00:11:07,590 --> 00:11:11,820 Like, if this condition is not true but this other condition is true. 231 00:11:11,820 --> 00:11:14,420 Python abbreviated this to just elif-- 232 00:11:14,420 --> 00:11:17,680 E-L-I-F, just short for else-if. 233 00:11:17,680 --> 00:11:23,760 So I can say elif n is less than zero, then let's go ahead and print out n 234 00:11:23,760 --> 00:11:30,920 is negative, and else print n is zero, 235 00:11:30,920 --> 00:11:33,800 So the idea here now is that if n is greater than zero, 236 00:11:33,800 --> 00:11:35,960 we perform some task elif-- 237 00:11:35,960 --> 00:11:38,060 in other words, if it's not greater than zero-- 238 00:11:38,060 --> 00:11:40,490 then we check to see if it is less than zero. 239 00:11:40,490 --> 00:11:42,950 In which case, we print out that n as negative. 240 00:11:42,950 --> 00:11:45,920 Else, if neither of those two conditions are true, it's not positive 241 00:11:45,920 --> 00:11:48,410 and it's not negative, the only remaining possibility 242 00:11:48,410 --> 00:11:49,700 is that n is zero. 243 00:11:49,700 --> 00:11:52,210 So we can print out that n zero. 244 00:11:52,210 --> 00:11:54,140 And so we might like for this program to work. 245 00:11:54,140 --> 00:11:57,520 But watch what happens if I now try and run conditions.py. 246 00:11:57,520 --> 00:12:00,080 Even though logically in our heads and looking at it now, 247 00:12:00,080 --> 00:12:05,150 it probably seems pretty logical, if I run Python conditions.py and type 248 00:12:05,150 --> 00:12:05,900 in a number-- 249 00:12:05,900 --> 00:12:10,080 I'll type in the number five, for example, just see what happens. 250 00:12:10,080 --> 00:12:12,140 All right, something weird just happened. 251 00:12:12,140 --> 00:12:14,720 And this is our very first Python exception, 252 00:12:14,720 --> 00:12:17,210 an error that happens because something didn't quite 253 00:12:17,210 --> 00:12:19,610 go right inside of our Python program. 254 00:12:19,610 --> 00:12:22,460 And over time, you'll begin to learn how to parse this exception, 255 00:12:22,460 --> 00:12:25,190 and understand what it means, and where to begin to debug. 256 00:12:25,190 --> 00:12:26,900 But learning how to read these exceptions 257 00:12:26,900 --> 00:12:29,000 and figure out how to deal with them is definitely 258 00:12:29,000 --> 00:12:32,530 a very valuable skill on your way to becoming a Python developer. 259 00:12:32,530 --> 00:12:35,600 And so let's see if we can figure out what this exception to saying. 260 00:12:35,600 --> 00:12:37,970 Oftentimes, I start by looking at the bottom. 261 00:12:37,970 --> 00:12:39,863 I see that there is a type error. 262 00:12:39,863 --> 00:12:42,030 That is the type of the exception that has happened. 263 00:12:42,030 --> 00:12:44,738 There are a lot of exceptions that can go wrong in Python, things 264 00:12:44,738 --> 00:12:46,640 that we can do that cause errors. 265 00:12:46,640 --> 00:12:48,890 In this case, it's a type error, which generally 266 00:12:48,890 --> 00:12:52,040 means that there's some mismatch of types, 267 00:12:52,040 --> 00:12:54,980 that Python expected something to be of one type 268 00:12:54,980 --> 00:12:57,552 but it turned out to be a different type. 269 00:12:57,552 --> 00:12:59,510 So let's try and understand what this might be. 270 00:12:59,510 --> 00:13:04,670 It says greater than sine, not supported between instances of stir, 271 00:13:04,670 --> 00:13:07,760 short for string, and int. 272 00:13:07,760 --> 00:13:09,085 So what does that mean? 273 00:13:09,085 --> 00:13:11,210 Well, I guess it means that the greater than symbol 274 00:13:11,210 --> 00:13:13,490 that checks if one thing is greater than another 275 00:13:13,490 --> 00:13:17,290 doesn't work if you're comparing a string to an integer. 276 00:13:17,290 --> 00:13:19,040 And that's probably pretty reasonable. 277 00:13:19,040 --> 00:13:22,063 It doesn't really make sense to say a string is greater than or less 278 00:13:22,063 --> 00:13:22,730 than an integer. 279 00:13:22,730 --> 00:13:24,680 When we're talking about greater than or less than, 280 00:13:24,680 --> 00:13:26,210 usually we're talking about numbers. 281 00:13:26,210 --> 00:13:29,100 So they should both be integers, for example. 282 00:13:29,100 --> 00:13:32,790 So why do we think that greater than is comparing a string and an integer? 283 00:13:32,790 --> 00:13:34,790 Well, now we can look a little bit further up 284 00:13:34,790 --> 00:13:38,180 at the trace-back, which will show which parts of the code 285 00:13:38,180 --> 00:13:39,568 are really causing this problem. 286 00:13:39,568 --> 00:13:41,610 And in this case, the trace-back is pretty short. 287 00:13:41,610 --> 00:13:44,800 It's just pointing me to a single line of a single file. 288 00:13:44,800 --> 00:13:49,160 It's saying in the file conditions.py on line three, 289 00:13:49,160 --> 00:13:54,890 here is the line that triggered the exception-- if n is greater than zero. 290 00:13:54,890 --> 00:13:56,600 So, what's the exception here? 291 00:13:56,600 --> 00:13:59,910 Well, zero is obviously an integer because that just is an integer. 292 00:13:59,910 --> 00:14:03,200 And so if greater than thinks that it's comparing a string with an integer, 293 00:14:03,200 --> 00:14:05,570 then n somehow must be a string. 294 00:14:05,570 --> 00:14:10,310 Even though I typed in the number five, it must still think n is a string. 295 00:14:10,310 --> 00:14:11,278 So why might that be? 296 00:14:11,278 --> 00:14:13,070 Let's take a look at the code again and see 297 00:14:13,070 --> 00:14:15,230 if we can figure out what's going on. 298 00:14:15,230 --> 00:14:19,700 Well, it seems that this input function doesn't care what you type in. 299 00:14:19,700 --> 00:14:22,490 It's always going to give you back a string. 300 00:14:22,490 --> 00:14:24,655 n somehow is ending up as a string, which 301 00:14:24,655 --> 00:14:26,780 is pretty reasonable because the input function has 302 00:14:26,780 --> 00:14:30,120 no idea whether I typed in a number, or whether I typed in a letter, 303 00:14:30,120 --> 00:14:32,150 or I typed in other characters altogether. 304 00:14:32,150 --> 00:14:36,380 So input doesn't know to give back its data in the form of an int, 305 00:14:36,380 --> 00:14:38,540 or in the form of a float, or in any other form. 306 00:14:38,540 --> 00:14:40,820 So by default, it's just going to return a string. 307 00:14:40,820 --> 00:14:45,737 What characters did the user type in as their input? 308 00:14:45,737 --> 00:14:48,320 So what I'd like to do now, in order to make this program work 309 00:14:48,320 --> 00:14:51,980 the way I want it to, is take this and convert it into an integer, 310 00:14:51,980 --> 00:14:56,030 or cast it into an integer, so to speak. 311 00:14:56,030 --> 00:14:59,630 And the way that I can do that is by using a function in Python 312 00:14:59,630 --> 00:15:04,050 called int, that takes anything and turns it into an integer. 313 00:15:04,050 --> 00:15:06,440 So here, I can say int-- 314 00:15:06,440 --> 00:15:09,590 and then as the argument to the int function, the input to the int 315 00:15:09,590 --> 00:15:14,602 function, I'm just going to include this whole expression, input number. 316 00:15:14,602 --> 00:15:16,560 So I'm going to ask the user to input a number. 317 00:15:16,560 --> 00:15:18,130 They type in some text. 318 00:15:18,130 --> 00:15:20,970 The input function gives me back a string. 319 00:15:20,970 --> 00:15:25,700 And that string is going to serve as the input to the int function, which 320 00:15:25,700 --> 00:15:30,070 then gets saved inside of this variable called n. 321 00:15:30,070 --> 00:15:32,800 So now that we know that n is indeed an integer, 322 00:15:32,800 --> 00:15:34,760 let's try and run this program again. 323 00:15:34,760 --> 00:15:38,710 I'll go back into the terminal, run Python, conditions.py, 324 00:15:38,710 --> 00:15:40,390 I'm asked to type in a number. 325 00:15:40,390 --> 00:15:42,430 I type in a number like five. 326 00:15:42,430 --> 00:15:45,897 And all right, that still doesn't seem to have worked. 327 00:15:45,897 --> 00:15:47,980 And it didn't work because I didn't save the file. 328 00:15:47,980 --> 00:15:51,580 So I'll go ahead and save the file, try it again, type in a number. 329 00:15:51,580 --> 00:15:53,950 And now we see that indeed, n is positive. 330 00:15:53,950 --> 00:15:55,360 We get no more exception. 331 00:15:55,360 --> 00:15:57,430 We were able to run the code successfully and see 332 00:15:57,430 --> 00:15:59,350 that the value of n is positive. 333 00:15:59,350 --> 00:16:02,440 And I could try this again to test the other conditional branches. 334 00:16:02,440 --> 00:16:06,480 Type in negative one for example to see that n is negative. 335 00:16:06,480 --> 00:16:09,340 And otherwise if it isn't either positive or negative, 336 00:16:09,340 --> 00:16:12,190 then we know that n is zero. 337 00:16:12,190 --> 00:16:15,310 And so here was our first exposure to conditions in Python, 338 00:16:15,310 --> 00:16:17,530 the ability to have multiple different branches 339 00:16:17,530 --> 00:16:20,710 and do different code depending on some expression 340 00:16:20,710 --> 00:16:22,510 that we're going to evaluate to either be 341 00:16:22,510 --> 00:16:26,440 a true expression or a false expression. 342 00:16:26,440 --> 00:16:29,190 All right, so let's take a look at some of the other features that 343 00:16:29,190 --> 00:16:31,710 are going to be present inside the Python language. 344 00:16:31,710 --> 00:16:34,080 And one of the most powerful features of Python 345 00:16:34,080 --> 00:16:36,510 are its various different types of sequences, 346 00:16:36,510 --> 00:16:39,600 data types that store values in some sort of sequence 347 00:16:39,600 --> 00:16:42,300 or some collection of values altogether. 348 00:16:42,300 --> 00:16:47,050 So I go ahead and create a new file that we'll call sequences.py. 349 00:16:47,050 --> 00:16:49,300 And there are a number of different types of sequences 350 00:16:49,300 --> 00:16:51,400 that all obey similar properties. 351 00:16:51,400 --> 00:16:54,620 But one of the types of sequences is the type we've already seen, 352 00:16:54,620 --> 00:16:56,990 which is just a string, for example. 353 00:16:56,990 --> 00:17:01,780 So if I have a name, and the name is something like Harry, for instance, 354 00:17:01,780 --> 00:17:07,240 and this sequence allows me to access individual elements inside 355 00:17:07,240 --> 00:17:08,460 of the sequence. 356 00:17:08,460 --> 00:17:11,650 And in order to do so, it's much like an array in other languages, 357 00:17:11,650 --> 00:17:13,510 if you've experienced them before. 358 00:17:13,510 --> 00:17:19,270 But I can print out name square bracket zero. 359 00:17:19,270 --> 00:17:21,550 This square bracket notation takes a sequence, 360 00:17:21,550 --> 00:17:24,310 some ordered sequence of elements, and gets 361 00:17:24,310 --> 00:17:28,339 me access to one particular element inside of that sequence. 362 00:17:28,339 --> 00:17:32,230 And so if I have a string-like name and I say name square bracket zero, 363 00:17:32,230 --> 00:17:35,320 the effect of that is going to be take this long sequence 364 00:17:35,320 --> 00:17:37,600 and get me the zero-th element. 365 00:17:37,600 --> 00:17:40,570 In many programming languages and in programming more generally, 366 00:17:40,570 --> 00:17:42,820 we often start counting things at zero. 367 00:17:42,820 --> 00:17:44,560 So the very first item in the sequence is 368 00:17:44,560 --> 00:17:47,200 item zero, the second item is item one. 369 00:17:47,200 --> 00:17:49,570 So it's easy to get slight off by one errors there. 370 00:17:49,570 --> 00:17:53,050 But just know that item zero of the name should be the first character 371 00:17:53,050 --> 00:17:54,150 in the name. 372 00:17:54,150 --> 00:17:57,250 And I can see that for sure, if I run Python-- 373 00:17:57,250 --> 00:18:00,822 I'll save this file, run Python sequences.py. 374 00:18:00,822 --> 00:18:04,510 And what I get is just the first character of Harry's name, which 375 00:18:04,510 --> 00:18:06,490 in this case is the letter H. 376 00:18:06,490 --> 00:18:09,550 If I instead asked to print out character one, which 377 00:18:09,550 --> 00:18:13,270 would be the second character in the name, if we run the program, 378 00:18:13,270 --> 00:18:15,610 now I get the letter a. 379 00:18:15,610 --> 00:18:18,760 And this type of indexing works for many different types of sequences, 380 00:18:18,760 --> 00:18:22,310 not just a string, which so happens to be a sequence of characters, 381 00:18:22,310 --> 00:18:23,650 but other types as well. 382 00:18:23,650 --> 00:18:27,020 Python, for example, has a type for lists of data. 383 00:18:27,020 --> 00:18:30,520 So if I have a sequence of any type of data that I want to store, 384 00:18:30,520 --> 00:18:34,480 I can store that information inside of a list in Python. 385 00:18:34,480 --> 00:18:36,700 So maybe instead of storing one name, I have 386 00:18:36,700 --> 00:18:38,680 multiple names that I want to store. 387 00:18:38,680 --> 00:18:44,160 So I want to store names like Harry, and Ron, and Hermione, for example. 388 00:18:44,160 --> 00:18:49,000 So now I have three names all stored in the sequence inside of a Python list. 389 00:18:49,000 --> 00:18:51,490 And I can-- you know, I can print out all of the names, 390 00:18:51,490 --> 00:18:53,740 for example, just to print out all of the names 391 00:18:53,740 --> 00:18:56,800 to see what the value of the variable names is equal to. 392 00:18:56,800 --> 00:18:59,170 And we'll see that when I do that, I get a printout 393 00:18:59,170 --> 00:19:00,430 of the contents of that list. 394 00:19:00,430 --> 00:19:03,470 Harry, Ron, Hermione, in that particular order. 395 00:19:03,470 --> 00:19:07,960 But you could also, much as you could index into a string, index into a list 396 00:19:07,960 --> 00:19:10,960 to say get me just the very first item inside 397 00:19:10,960 --> 00:19:14,790 of this names list, which in this case, when I run the program, 398 00:19:14,790 --> 00:19:16,348 is going to just be Harry. 399 00:19:16,348 --> 00:19:18,390 So there are a number of different sequence types 400 00:19:18,390 --> 00:19:21,110 that you can use in order to represent data. 401 00:19:21,110 --> 00:19:24,580 Another one just so happens to be called a tuple. 402 00:19:24,580 --> 00:19:27,370 And a tuple is often used if you have a couple of values 403 00:19:27,370 --> 00:19:30,130 that aren't going to change but you need to store 404 00:19:30,130 --> 00:19:32,230 a pair of values like two values together, 405 00:19:32,230 --> 00:19:34,487 or three values together, or something like it. 406 00:19:34,487 --> 00:19:36,820 You might imagine that if were writing a program to deal 407 00:19:36,820 --> 00:19:39,770 with graphing in two dimensions, for example, 408 00:19:39,770 --> 00:19:45,030 you might want to represent a point as an x value and a y value. 409 00:19:45,030 --> 00:19:46,840 And you could create two variables for it. 410 00:19:46,840 --> 00:19:49,030 I could say, you know, let me do, say, a coordinate 411 00:19:49,030 --> 00:19:51,760 x is going to be equal to 10.0. 412 00:19:51,760 --> 00:19:54,560 And coordinate y is equal to 20.0. 413 00:19:54,560 --> 00:19:59,650 But now I'm creating two variables for what's really one unit that 414 00:19:59,650 --> 00:20:02,140 just so happens to have two parts. 415 00:20:02,140 --> 00:20:05,410 And so to represent this, we can use a tuple in Python, 416 00:20:05,410 --> 00:20:12,280 and just say something like coordinate equals 10.0 comma 20.0. 417 00:20:12,280 --> 00:20:15,190 So whereas in lists we use square brackets to denote 418 00:20:15,190 --> 00:20:18,280 where the list begins and where the list ends, in a tuple, 419 00:20:18,280 --> 00:20:21,760 we just use parentheses to say we're grouping a number of values together, 420 00:20:21,760 --> 00:20:25,610 we're grouping one value, 10.0, with a second value, 20.0. 421 00:20:25,610 --> 00:20:28,780 And now we can pass around these two values as a single unit 422 00:20:28,780 --> 00:20:32,590 just by referencing them using the single name, which in this case 423 00:20:32,590 --> 00:20:34,090 is coordinate. 424 00:20:34,090 --> 00:20:37,500 So there are a number of different types of these various different sequences. 425 00:20:37,500 --> 00:20:41,980 And some of those sequences we'll take a look at are these data structures here. 426 00:20:41,980 --> 00:20:45,120 So list, for example, is a sequence of mutable values, 427 00:20:45,120 --> 00:20:46,120 which we took a look at. 428 00:20:46,120 --> 00:20:49,360 And mutable, just meaning we can change the elements in the list. 429 00:20:49,360 --> 00:20:52,310 If I have a list, I can add something to the end of the list, 430 00:20:52,310 --> 00:20:56,370 I can delete something from the list, I can modify the values inside the list. 431 00:20:56,370 --> 00:20:59,860 A tuple, on the other hand, is a sequence of immutable values 432 00:20:59,860 --> 00:21:03,910 those values can't change you can't add another element to the existing tuple. 433 00:21:03,910 --> 00:21:06,478 You'd have to create a new tuple in order to do so. 434 00:21:06,478 --> 00:21:08,770 And there are other data structures that exist as well. 435 00:21:08,770 --> 00:21:10,687 A couple that we'll take a look at in a moment 436 00:21:10,687 --> 00:21:14,387 include sets, which are a collection of unique values. 437 00:21:14,387 --> 00:21:16,970 So if you're familiar with sets from the world of mathematics, 438 00:21:16,970 --> 00:21:20,260 it's a very similar idea, that whereas a list in a tuple 439 00:21:20,260 --> 00:21:23,200 keeps things in a particular order, a set 440 00:21:23,200 --> 00:21:25,240 does not keep things in any particular order. 441 00:21:25,240 --> 00:21:26,710 It's just a collection. 442 00:21:26,710 --> 00:21:29,560 And in particular, all of the values need to be unique. 443 00:21:29,560 --> 00:21:31,990 In a list or in a tuple, you might have the same value 444 00:21:31,990 --> 00:21:33,070 appearing multiple times. 445 00:21:33,070 --> 00:21:36,650 And in a set, every value appears exactly once. 446 00:21:36,650 --> 00:21:38,650 And there are some advantages to sets, some ways 447 00:21:38,650 --> 00:21:40,660 that you can make your programs more efficient 448 00:21:40,660 --> 00:21:43,618 by using sets if you know that you just need a collection, 449 00:21:43,618 --> 00:21:45,910 if you don't care about the order, if something is only 450 00:21:45,910 --> 00:21:48,320 going to show up exactly once at most, then 451 00:21:48,320 --> 00:21:51,590 you can use a set to potentially make your programs a little more efficient 452 00:21:51,590 --> 00:21:53,900 and a little more elegantly designed. 453 00:21:53,900 --> 00:21:56,600 And finally, one other data structure that's quite powerful 454 00:21:56,600 --> 00:21:59,570 and that's going to come up a number of times during this course 455 00:21:59,570 --> 00:22:00,740 is a dictionary. 456 00:22:00,740 --> 00:22:02,750 In Python, shortened to just a dict, which 457 00:22:02,750 --> 00:22:06,270 is the collection of what we're going to call key-value pairs. 458 00:22:06,270 --> 00:22:09,470 And the way I like to think of this as with an actual physical dictionary 459 00:22:09,470 --> 00:22:12,830 that you might find in the library that maps words to their definitions. 460 00:22:12,830 --> 00:22:16,850 In a physical dictionary, you open up the dictionary and you look up a word 461 00:22:16,850 --> 00:22:18,890 and you get the definition. 462 00:22:18,890 --> 00:22:21,000 And a dict in Python is going to be very similar. 463 00:22:21,000 --> 00:22:23,690 It's going to be a data structure where I can look something up 464 00:22:23,690 --> 00:22:28,490 by one keyword or one value and get some other value as a result. 465 00:22:28,490 --> 00:22:31,550 We call the thing that I'm looking up the key. 466 00:22:31,550 --> 00:22:35,060 And we call what I get when I do the looking up the value. 467 00:22:35,060 --> 00:22:37,070 So we keep pairs of keys and values. 468 00:22:37,070 --> 00:22:40,010 In the case of an actual dictionary in the real world, 469 00:22:40,010 --> 00:22:44,020 the key is the word that we want to look up and the value is its definition. 470 00:22:44,020 --> 00:22:48,320 But we can use this more generally in Python anytime we want to map something 471 00:22:48,320 --> 00:22:52,280 to some other value such that we can very easily look up that value 472 00:22:52,280 --> 00:22:54,290 inside of this data structure. 473 00:22:54,290 --> 00:22:57,450 So we'll see examples of dictionaries as well. 474 00:22:57,450 --> 00:23:00,560 So let's now explore the first of these data structures, these lists, 475 00:23:00,560 --> 00:23:03,230 to explore what we can do by taking advantage 476 00:23:03,230 --> 00:23:07,500 of the features that are given to us by a Python list, for example. 477 00:23:07,500 --> 00:23:14,078 So we'll go ahead and create a new program that I'll call lists.py. 478 00:23:14,078 --> 00:23:17,280 And here, I'm just going to create a list of names. 479 00:23:17,280 --> 00:23:23,530 So names equals Harry, Ron, Hermione, and Ginny, for example. 480 00:23:23,530 --> 00:23:25,630 And as I start to write multiple lines of code, 481 00:23:25,630 --> 00:23:28,240 especially as my Python programs start getting longer, 482 00:23:28,240 --> 00:23:31,110 it can be a good idea to document what it is that I'm doing. 483 00:23:31,110 --> 00:23:34,740 So I can say, let me add a comment to this particular line of code 484 00:23:34,740 --> 00:23:37,770 just so I know what it is that I've done in this line of code. 485 00:23:37,770 --> 00:23:40,770 And in Python, there are a couple of different ways to create a comment. 486 00:23:40,770 --> 00:23:45,570 But the simplest way is just to use the pound sign or the hashtag. 487 00:23:45,570 --> 00:23:48,420 As soon as you include that, everything after that for the remainder 488 00:23:48,420 --> 00:23:50,290 of the line is a comment. 489 00:23:50,290 --> 00:23:52,290 The interpreter is going to ignore that comment. 490 00:23:52,290 --> 00:23:53,790 You can say whatever you want. 491 00:23:53,790 --> 00:23:56,400 It's more for you, the programmer and for someone 492 00:23:56,400 --> 00:23:59,130 who's reading your program to be able to look at the program, 493 00:23:59,130 --> 00:24:03,280 understand what it's saying, and figure out what they need to do about it. 494 00:24:03,280 --> 00:24:06,000 So I can just say, define a list of names, 495 00:24:06,000 --> 00:24:09,960 for example, just to make it clear to me what it is that I have done inside 496 00:24:09,960 --> 00:24:11,640 of this line of code. 497 00:24:11,640 --> 00:24:14,940 So I can print out that list of names, as we've done before. 498 00:24:14,940 --> 00:24:19,005 And we'll see that when I print out that list of names, what I get is-- 499 00:24:19,005 --> 00:24:21,930 oh, let me run list.py. 500 00:24:21,930 --> 00:24:23,100 What I get is this list-- 501 00:24:23,100 --> 00:24:25,468 Harry, Ron, Hermione, and Ginny. 502 00:24:25,468 --> 00:24:27,510 But I could also print out, as we've seen before, 503 00:24:27,510 --> 00:24:28,760 just the first of those names. 504 00:24:28,760 --> 00:24:32,460 Say, you know, print out just names square bracket zero, in which case 505 00:24:32,460 --> 00:24:36,190 I'm going to get just Harry, for example. 506 00:24:36,190 --> 00:24:38,440 But now, recall that a list is mutable. 507 00:24:38,440 --> 00:24:42,340 I can modify the elements that happen to exist inside of this list. 508 00:24:42,340 --> 00:24:49,630 So I could say names.apped a new name, something like Draco, for example. 509 00:24:49,630 --> 00:24:53,340 And so lists have a number of built in methods or functions which 510 00:24:53,340 --> 00:24:56,550 are functions that I can run on an existing list 511 00:24:56,550 --> 00:24:58,590 to access particular elements of the list 512 00:24:58,590 --> 00:25:00,780 or to modify the list in particular ways. 513 00:25:00,780 --> 00:25:03,810 And in the case of a list, the append method 514 00:25:03,810 --> 00:25:06,420 is a method or function that I can run that just adds 515 00:25:06,420 --> 00:25:09,010 a value to the end of an existing list. 516 00:25:09,010 --> 00:25:11,090 So I've added Draco to the list. 517 00:25:11,090 --> 00:25:14,610 And there are a number of other methods that I can use on lists, one of which 518 00:25:14,610 --> 00:25:16,523 is, for example, sorting a list. 519 00:25:16,523 --> 00:25:18,690 No need to write your own sorting algorithm in order 520 00:25:18,690 --> 00:25:20,670 to sort a sequence of objects. 521 00:25:20,670 --> 00:25:23,640 In Python, there is a built-in sort method 522 00:25:23,640 --> 00:25:26,850 that works on lists where I can just say names.sort. 523 00:25:26,850 --> 00:25:29,340 That will automatically sort everything in the list. 524 00:25:29,340 --> 00:25:32,220 And now if I print out all of those names-- 525 00:25:32,220 --> 00:25:36,960 go to print them out and get rid of this old print statement-- 526 00:25:36,960 --> 00:25:39,450 now we see that we get five names that are printed out 527 00:25:39,450 --> 00:25:42,150 because I had four elements originally in this list 528 00:25:42,150 --> 00:25:43,710 but then I added a fifth one. 529 00:25:43,710 --> 00:25:46,750 And notice now that they are actually in alphabetical order, 530 00:25:46,750 --> 00:25:49,140 starting with Draco, ending with Ron because I 531 00:25:49,140 --> 00:25:52,920 was able to sort the list by modifying the order in which those elements 532 00:25:52,920 --> 00:25:54,820 actually show up. 533 00:25:54,820 --> 00:25:56,940 And so list can definitely quite powerful anytime 534 00:25:56,940 --> 00:25:59,520 you need to store elements in order, a list 535 00:25:59,520 --> 00:26:02,940 is definitely a useful tool that Python gives to you. 536 00:26:02,940 --> 00:26:05,430 If you don't care about the order of the elements though, 537 00:26:05,430 --> 00:26:08,550 and if you know that all the elements are going to be unique, 538 00:26:08,550 --> 00:26:11,130 then you can use a set, which is another Python data 539 00:26:11,130 --> 00:26:12,960 structure that works in similar ways. 540 00:26:12,960 --> 00:26:15,820 The syntax is slightly different. 541 00:26:15,820 --> 00:26:17,550 So let's do an example with those. 542 00:26:17,550 --> 00:26:20,940 I'll create a new file, call it sets.py. 543 00:26:20,940 --> 00:26:23,490 And let me first create an empty set. 544 00:26:23,490 --> 00:26:25,540 And we can do that by just saying s equals-- 545 00:26:25,540 --> 00:26:28,410 s is going to be the variable that will store my set. 546 00:26:28,410 --> 00:26:30,990 And I'll say set and then parentheses. 547 00:26:30,990 --> 00:26:33,570 That will just create an empty set that just so happens 548 00:26:33,570 --> 00:26:38,190 to have nothing inside of it now we'll add some elements to the set 549 00:26:38,190 --> 00:26:40,800 so I can say s.add. 550 00:26:40,800 --> 00:26:42,900 Let's add the number one to the set. 551 00:26:42,900 --> 00:26:44,700 Let's add the number two. 552 00:26:44,700 --> 00:26:45,900 Let's add that number three. 553 00:26:45,900 --> 00:26:48,430 And let's add the number four. 554 00:26:48,430 --> 00:26:52,550 And then we can print out the set to see what happens to be inside the set 555 00:26:52,550 --> 00:26:54,350 right now. 556 00:26:54,350 --> 00:27:00,520 Now when I run this program, Python sets.py, we see that inside the set 557 00:27:00,520 --> 00:27:03,205 are four values, one, two, three, and four. 558 00:27:03,205 --> 00:27:04,330 They happen to be in order. 559 00:27:04,330 --> 00:27:05,980 But sets are not naturally ordered. 560 00:27:05,980 --> 00:27:08,980 They're not going to always keep track of what the order is going to be. 561 00:27:08,980 --> 00:27:09,950 But I can add-- 562 00:27:09,950 --> 00:27:14,580 for example, if I add three again to the set, now I've added three to the set 563 00:27:14,580 --> 00:27:15,130 twice. 564 00:27:15,130 --> 00:27:19,060 I added one, two, three, four, and then three again. 565 00:27:19,060 --> 00:27:20,770 When I print out the contents of the set, 566 00:27:20,770 --> 00:27:24,400 it still just contains the elements one, two, three, four. 567 00:27:24,400 --> 00:27:26,790 No element ever appears twice in the set, 568 00:27:26,790 --> 00:27:28,540 following with the mathematical definition 569 00:27:28,540 --> 00:27:34,160 of a set where no element ever appears more than once inside of a set. 570 00:27:34,160 --> 00:27:36,360 You can also remove elements from sets as well. 571 00:27:36,360 --> 00:27:39,720 So if I wanted to remove the number two from the set for example, 572 00:27:39,720 --> 00:27:43,760 I could say s.remove2 and then print out s 573 00:27:43,760 --> 00:27:48,060 to say print out whatever happens to be inside of that set now. 574 00:27:48,060 --> 00:27:50,170 And now when I rerun this program, I only 575 00:27:50,170 --> 00:27:55,090 get one, three, and four because I removed two from the set. 576 00:27:55,090 --> 00:27:57,670 So sets allow you to add to them, remove from them. 577 00:27:57,670 --> 00:28:02,020 And also, all sequences, whether they be strings, or lists, or sets, 578 00:28:02,020 --> 00:28:04,550 allow you to get how many elements are in the set 579 00:28:04,550 --> 00:28:08,830 by taking advantage of a function built into Python called len. 580 00:28:08,830 --> 00:28:12,550 So len we'll give you the length of a sequence, so the number of items 581 00:28:12,550 --> 00:28:16,000 inside of a list, or the number of characters inside of a string, 582 00:28:16,000 --> 00:28:18,700 or the number of elements inside of a set. 583 00:28:18,700 --> 00:28:22,030 And so, if I wanted to print out how many elements are in the set, 584 00:28:22,030 --> 00:28:23,650 I might do something like this. 585 00:28:23,650 --> 00:28:31,390 In a formatted string, say the set has some number of elements. 586 00:28:31,390 --> 00:28:33,110 And how do I know how many elements? 587 00:28:33,110 --> 00:28:35,210 Well, again, inside of these curly braces, 588 00:28:35,210 --> 00:28:38,510 I can include any expression in Python that I would 589 00:28:38,510 --> 00:28:40,980 like to substitute into this string. 590 00:28:40,980 --> 00:28:42,590 So how many elements are in the set? 591 00:28:42,590 --> 00:28:47,210 I can get that by calculating len of s. 592 00:28:47,210 --> 00:28:50,165 So what I've done here is I've said with len of s, 593 00:28:50,165 --> 00:28:53,070 I would like to calculate the length of the set, s, in other words, 594 00:28:53,070 --> 00:28:55,940 how many elements are actually inside of that set. 595 00:28:55,940 --> 00:28:59,150 And then using this curly brace notation, I'm saying, take that number 596 00:28:59,150 --> 00:29:01,460 and plug it into this string so we can see the set 597 00:29:01,460 --> 00:29:05,610 has some number of elements, for example. 598 00:29:05,610 --> 00:29:09,338 So now if I run this program, Python sets.py, 599 00:29:09,338 --> 00:29:12,380 I see that I get these three elements that happen to be inside of the set 600 00:29:12,380 --> 00:29:15,590 right now, which is one, and then three, and then four. 601 00:29:15,590 --> 00:29:19,160 And then it tells me that the set has three elements inside 602 00:29:19,160 --> 00:29:23,515 of it, which is the number of elements that are in the set right now. 603 00:29:23,515 --> 00:29:26,640 So now we've seen a number of different language features inside of Python. 604 00:29:26,640 --> 00:29:28,035 We've seen variables. 605 00:29:28,035 --> 00:29:31,160 We've seen conditions so that we can conditionally do things-- if something 606 00:29:31,160 --> 00:29:33,260 is true, if something else is true. 607 00:29:33,260 --> 00:29:35,300 And we've seen some of the data structures 608 00:29:35,300 --> 00:29:38,990 that are core to the way Python works-- lists, and sets, and tuples, 609 00:29:38,990 --> 00:29:41,293 and other data structures that can be helpful too. 610 00:29:41,293 --> 00:29:44,210 And now let's take a look at another feature of the Python programming 611 00:29:44,210 --> 00:29:47,390 language common to many programming languages, the idea of looping. 612 00:29:47,390 --> 00:29:50,730 If I want to be able to do something multiple times, 613 00:29:50,730 --> 00:29:54,182 I'll go ahead and create a new file called loops.py. 614 00:29:54,182 --> 00:29:56,180 And let's just create a simple loop. 615 00:29:56,180 --> 00:29:58,280 The simplest loop we could create in Python 616 00:29:58,280 --> 00:30:01,350 is just one that's going to count a bunch of numbers. 617 00:30:01,350 --> 00:30:04,520 So in order to do that, what I could say is something like this. 618 00:30:04,520 --> 00:30:10,070 For i in one, two, three, four, five-- 619 00:30:10,070 --> 00:30:12,880 or maybe I want to count zero, one, two, three, four, five, just 620 00:30:12,880 --> 00:30:14,500 to start counting at zero-- 621 00:30:14,500 --> 00:30:17,111 print i. 622 00:30:17,111 --> 00:30:20,740 And so here's the basic syntax for a Python loop. 623 00:30:20,740 --> 00:30:22,510 And here's what seems to be going on. 624 00:30:22,510 --> 00:30:25,600 Over here on the very first line, I have a Python list 625 00:30:25,600 --> 00:30:29,540 as denoted by those square brackets that contains six numbers-- 626 00:30:29,540 --> 00:30:31,750 zero, one, two, three, four, five. 627 00:30:31,750 --> 00:30:35,930 And now I have a for loop-- for i in this list. 628 00:30:35,930 --> 00:30:39,640 And the way Python interprets this is to say, go through this list one 629 00:30:39,640 --> 00:30:40,860 element to the time. 630 00:30:40,860 --> 00:30:43,557 And for each element, call that element i. 631 00:30:43,557 --> 00:30:44,890 You could've called it anything. 632 00:30:44,890 --> 00:30:47,140 But in this case, i is just a conventional choice 633 00:30:47,140 --> 00:30:49,000 for a number that keeps incrementing. 634 00:30:49,000 --> 00:30:52,810 And we're going to print out now the value of i 635 00:30:52,810 --> 00:30:55,670 for each iteration of this loop. 636 00:30:55,670 --> 00:31:00,400 So we try this out now and run Python loops.py. 637 00:31:00,400 --> 00:31:02,920 We see zero, one, two, three, four, five. 638 00:31:02,920 --> 00:31:06,880 Great, it printed out all of the numbers from zero to five one at a time. 639 00:31:06,880 --> 00:31:10,300 In practice though, if we wanted to count all the way up to five 640 00:31:10,300 --> 00:31:14,470 or print six numbers for example, this is fine for now. 641 00:31:14,470 --> 00:31:17,470 But if we wanted to print like 100 numbers or 1,000 numbers, 642 00:31:17,470 --> 00:31:19,720 this is going to start to get tedious. 643 00:31:19,720 --> 00:31:23,920 So Python has a built-in function called range 644 00:31:23,920 --> 00:31:28,480 where I can say for i in range six to achieve exactly the same thing. 645 00:31:28,480 --> 00:31:31,520 Range six means get me a range of six numbers. 646 00:31:31,520 --> 00:31:35,140 So if we start at zero, it's going to go from zero all the way up to five. 647 00:31:35,140 --> 00:31:39,130 And then we can print out each one of the elements inside of that sequence. 648 00:31:39,130 --> 00:31:44,770 So if I rerun in Python loops.py, we get zero, one, two, three, four, five. 649 00:31:44,770 --> 00:31:48,250 So loops enable us to loop over any type of sequence. 650 00:31:48,250 --> 00:31:51,220 So if the sequence is a list, I can say something like, 651 00:31:51,220 --> 00:31:56,830 if I have a list of names like Harry, and Ron, and Hermione, 652 00:31:56,830 --> 00:31:59,370 and this is my list of names, I can have a loop that 653 00:31:59,370 --> 00:32:05,010 says that for each name in my list of names, let's print out that name, 654 00:32:05,010 --> 00:32:06,200 for example. 655 00:32:06,200 --> 00:32:07,020 So we have a list. 656 00:32:07,020 --> 00:32:08,180 The list is called Names. 657 00:32:08,180 --> 00:32:11,520 We're looping over it one element at a time and printing it out. 658 00:32:11,520 --> 00:32:15,510 Now if I run the program, I see three names printed one on each line. 659 00:32:15,510 --> 00:32:17,880 And you can do this for other sequences as well. 660 00:32:17,880 --> 00:32:21,660 Maybe I have just a single name that is called Harry. 661 00:32:21,660 --> 00:32:26,190 And now I can have a line that says, you know, for every character in that name, 662 00:32:26,190 --> 00:32:28,500 print the character. 663 00:32:28,500 --> 00:32:31,740 If the name is the sequence, is a sequence of individual characters 664 00:32:31,740 --> 00:32:34,620 because it's a string, then when I loop over to that string, 665 00:32:34,620 --> 00:32:38,140 I'll be looping over each individual character in that string. 666 00:32:38,140 --> 00:32:41,190 So I can run the program and see one on each line, 667 00:32:41,190 --> 00:32:47,280 each of the letters that just so happens to be inside of Harry's name. 668 00:32:47,280 --> 00:32:48,570 So now we've seen conditions. 669 00:32:48,570 --> 00:32:49,390 We've seen loops. 670 00:32:49,390 --> 00:32:51,598 And we've seen a number of different data structures. 671 00:32:51,598 --> 00:32:54,678 We've seen lists, and sets, as well as tuples. 672 00:32:54,678 --> 00:32:57,720 The last important data structure that we're going to be taking a look at 673 00:32:57,720 --> 00:33:00,120 are Python dictionaries which, as you'll recall, 674 00:33:00,120 --> 00:33:02,490 are some mapping of keys to values. 675 00:33:02,490 --> 00:33:04,290 If I want to be able to look something up, 676 00:33:04,290 --> 00:33:07,260 I can use a Python dictionary just as a data structure to be 677 00:33:07,260 --> 00:33:09,930 able to store these sorts of values. 678 00:33:09,930 --> 00:33:13,797 So I'll create a new file called dictionaries.py. 679 00:33:13,797 --> 00:33:15,630 And maybe I want to create a dictionary that 680 00:33:15,630 --> 00:33:20,760 is going to keep track of, say, what house each of the students at Hogwarts 681 00:33:20,760 --> 00:33:21,910 happen to be in. 682 00:33:21,910 --> 00:33:24,630 So I might have a dictionary called Houses. 683 00:33:24,630 --> 00:33:28,080 And the way we specify a dictionary is by specifying 684 00:33:28,080 --> 00:33:32,880 a key colon of value when we're defining a dictionary for the first time. 685 00:33:32,880 --> 00:33:41,360 So I might say Harry colon Gryffindor and then Draco colon Slytherin, 686 00:33:41,360 --> 00:33:42,870 for example. 687 00:33:42,870 --> 00:33:46,280 And so what this line of code is doing is it is creating a new dictionary. 688 00:33:46,280 --> 00:33:47,990 This dictionary is called Houses. 689 00:33:47,990 --> 00:33:52,250 And inside this dictionary, I have two keys, two things that I can look up. 690 00:33:52,250 --> 00:33:55,070 I can look up Harry or I can look up Draco. 691 00:33:55,070 --> 00:34:00,170 And when I look up those keys, I get the value that follows their colon. 692 00:34:00,170 --> 00:34:04,400 So after Harry, if I look up Harry, I get Gryffindor If I look up Draco, 693 00:34:04,400 --> 00:34:05,900 I get Slytherin, for example. 694 00:34:05,900 --> 00:34:08,750 695 00:34:08,750 --> 00:34:13,090 So now if I wanted to print out what house Harry is in, 696 00:34:13,090 --> 00:34:18,060 I can print out houses square brackets Harry. 697 00:34:18,060 --> 00:34:20,409 So I can here, say, I would like to print out-- 698 00:34:20,409 --> 00:34:22,300 take the Houses dictionary. 699 00:34:22,300 --> 00:34:24,760 And the square bracket notation is how I look 700 00:34:24,760 --> 00:34:26,800 something up inside of a dictionary. 701 00:34:26,800 --> 00:34:30,040 It's similar to how we use square brackets to look up a specific element 702 00:34:30,040 --> 00:34:34,000 inside of a list to say, like, get me element zero or element one. 703 00:34:34,000 --> 00:34:36,400 In this case, we're using a Python dictionary 704 00:34:36,400 --> 00:34:40,360 to say, take the Houses dictionary and look up Harry's value, which 705 00:34:40,360 --> 00:34:42,070 hopefully should be Gryffindor. 706 00:34:42,070 --> 00:34:45,340 And we'll see that if we look up run Python dictionaries.py, 707 00:34:45,340 --> 00:34:49,810 we do get Gryffindor as the value of Harry's house. 708 00:34:49,810 --> 00:34:53,650 We can add things to this dictionary as well using the same syntax. 709 00:34:53,650 --> 00:34:56,620 In the same way that I use square brackets to access the value 710 00:34:56,620 --> 00:35:00,190 inside of a dictionary, if I want to change the value in a dictionary 711 00:35:00,190 --> 00:35:06,040 or add something new to it, I could say houses and Hermione, 712 00:35:06,040 --> 00:35:10,580 and say that Hermione is also in Gryffindor, for example. 713 00:35:10,580 --> 00:35:14,740 And so this line of code here says take the Houses dictionary 714 00:35:14,740 --> 00:35:18,130 and look up Hermione in the Houses dictionary. 715 00:35:18,130 --> 00:35:22,380 And when you do, that should be set equal to this value here, Gryffindor. 716 00:35:22,380 --> 00:35:26,470 So we took that value and we are going to assign it to Hermione inside 717 00:35:26,470 --> 00:35:29,090 of the dictionary, such that now if we wanted to, 718 00:35:29,090 --> 00:35:33,400 we could print out Hermione's house as well, run the program, 719 00:35:33,400 --> 00:35:36,040 and see that Hermione is also in Gryffindor. 720 00:35:36,040 --> 00:35:39,470 So anytime we want to be able to map some value to some other volume, 721 00:35:39,470 --> 00:35:42,160 whether we're mapping people to what house they happen to be in 722 00:35:42,160 --> 00:35:44,890 or we're mapping users to some information about those users 723 00:35:44,890 --> 00:35:46,960 inside of our web application, dictionaries 724 00:35:46,960 --> 00:35:52,570 are going to be very, very powerful tools for us to be able to do that. 725 00:35:52,570 --> 00:35:54,900 The next Python language feature we'll take a look at 726 00:35:54,900 --> 00:35:56,760 are functions in Python that are going to be 727 00:35:56,760 --> 00:35:59,880 some way for us to write our own functions that take an input 728 00:35:59,880 --> 00:36:01,107 and produce some output. 729 00:36:01,107 --> 00:36:04,440 We've already seen a number of different functions that already exist in Python. 730 00:36:04,440 --> 00:36:07,770 We've seen the input function that takes an input from the user. 731 00:36:07,770 --> 00:36:11,280 We've seen the print function that takes some text or some other information 732 00:36:11,280 --> 00:36:12,760 and prints it to the screen. 733 00:36:12,760 --> 00:36:17,020 But if we want to define our own functions, we can do so as well. 734 00:36:17,020 --> 00:36:21,520 So here I'll go ahead and write a new program called functions.py. 735 00:36:21,520 --> 00:36:25,410 And let's write a function that takes a number and squares it. 736 00:36:25,410 --> 00:36:28,170 So the square of 10 is 10 times 10, or 100. 737 00:36:28,170 --> 00:36:33,060 I would like a function that very easily takes a number and returns its square. 738 00:36:33,060 --> 00:36:36,330 The way I define a function in Python is using the def keyword. 739 00:36:36,330 --> 00:36:38,100 Def, short for define. 740 00:36:38,100 --> 00:36:41,640 And here I can say, let me define a function called square 741 00:36:41,640 --> 00:36:44,340 and then, in parentheses, what inputs it takes. 742 00:36:44,340 --> 00:36:47,340 In this case, square just takes a single input that I'm going to call x. 743 00:36:47,340 --> 00:36:50,215 But if there were multiple inputs, I could separate them with commas, 744 00:36:50,215 --> 00:36:53,680 like x, y, z for a function that took three inputs, for example. 745 00:36:53,680 --> 00:36:57,170 But in this case, there is just a single input, x. 746 00:36:57,170 --> 00:36:59,640 And the square function could have any logic 747 00:36:59,640 --> 00:37:02,430 in it indented underneath the square function. 748 00:37:02,430 --> 00:37:04,690 But ultimately, this function is fairly simple. 749 00:37:04,690 --> 00:37:10,490 All it's going to do is return x times x, x multiplied by itself. 750 00:37:10,490 --> 00:37:14,420 And now, if I want to print out a whole bunch of squares of numbers, 751 00:37:14,420 --> 00:37:15,410 I can do so. 752 00:37:15,410 --> 00:37:25,680 I can say for i in range, let's say, 10, let's print out that the square of i 753 00:37:25,680 --> 00:37:30,110 is square i. 754 00:37:30,110 --> 00:37:32,110 So let's try and parse out what's going on here. 755 00:37:32,110 --> 00:37:35,230 Line four says for i in range 10, do some loop 756 00:37:35,230 --> 00:37:37,957 10 times, looping from zero all the way up to nine. 757 00:37:37,957 --> 00:37:40,540 And for each time we loop, we're going to print something out. 758 00:37:40,540 --> 00:37:42,640 We're going to print out the square of-- 759 00:37:42,640 --> 00:37:44,470 plug in the value of i here-- 760 00:37:44,470 --> 00:37:51,120 is-- plug in the value of calling our square function using i as input. 761 00:37:51,120 --> 00:37:54,060 So that is going to have the result of running this loop 10 times 762 00:37:54,060 --> 00:37:56,490 and printing out this line 10 different times, 763 00:37:56,490 --> 00:37:59,530 each with a different value of i. 764 00:37:59,530 --> 00:38:01,263 So I can run Python functions.py. 765 00:38:01,263 --> 00:38:02,180 And here's what I see. 766 00:38:02,180 --> 00:38:03,380 The square of zero is zero. 767 00:38:03,380 --> 00:38:06,270 Square of one is one two is four, so on and so forth, 768 00:38:06,270 --> 00:38:09,170 all the way up to the square of 9 is 81. 769 00:38:09,170 --> 00:38:12,050 So we've now written a function and been able to use it. 770 00:38:12,050 --> 00:38:13,820 But ideally, when we write functions, we'd 771 00:38:13,820 --> 00:38:16,830 like to not just be able to use them in the same file, 772 00:38:16,830 --> 00:38:20,060 but for others to be able to use them as well. 773 00:38:20,060 --> 00:38:21,600 And so how can we do that? 774 00:38:21,600 --> 00:38:25,790 Well, in order to do that, you can import functions from other Python 775 00:38:25,790 --> 00:38:28,290 modules or files, so to speak. 776 00:38:28,290 --> 00:38:33,740 So let me create a new file called squares.py, for example. 777 00:38:33,740 --> 00:38:37,100 So that instead of running this loop here, let's 778 00:38:37,100 --> 00:38:41,330 instead run this loop in squares.py, again, 779 00:38:41,330 --> 00:38:43,220 separating out different parts of my code. 780 00:38:43,220 --> 00:38:47,690 I have one file that defines the square function inside of functions.py 781 00:38:47,690 --> 00:38:50,630 and then another file called squares.py, where I'm actually 782 00:38:50,630 --> 00:38:54,440 calling the square function. 783 00:38:54,440 --> 00:38:58,818 Now if I try to run Python squares.py, you'll notice I'll run into an error. 784 00:38:58,818 --> 00:39:00,860 Here's another error you'll see quite frequently. 785 00:39:00,860 --> 00:39:03,140 It's a name error, another type of exception. 786 00:39:03,140 --> 00:39:06,765 Which here says the name square is not defined, 787 00:39:06,765 --> 00:39:09,140 meaning I'm trying to use a variable, or a function name, 788 00:39:09,140 --> 00:39:12,380 or something else that doesn't actually have a definition. 789 00:39:12,380 --> 00:39:14,900 I've never said what square is. 790 00:39:14,900 --> 00:39:18,470 And that's because by default, Python files don't know about each other. 791 00:39:18,470 --> 00:39:22,250 If I want to use a function that was defined inside of another file, 792 00:39:22,250 --> 00:39:24,860 I need to import it from that file. 793 00:39:24,860 --> 00:39:26,900 And I can do so like so. 794 00:39:26,900 --> 00:39:32,370 I can say, from functions import square. 795 00:39:32,370 --> 00:39:35,310 Functions was the name of this file, functions.py. 796 00:39:35,310 --> 00:39:38,040 And I'm saying from that Python module, I 797 00:39:38,040 --> 00:39:42,980 would like to import the square function as a function that I would like to use. 798 00:39:42,980 --> 00:39:47,040 Now I can run Python squares.py. 799 00:39:47,040 --> 00:39:48,660 And we get the output that we expect-- 800 00:39:48,660 --> 00:39:50,370 no more exception. 801 00:39:50,370 --> 00:39:55,050 I've now been able to import something from another module 802 00:39:55,050 --> 00:39:56,630 and access it this way. 803 00:39:56,630 --> 00:39:58,380 So this is one way to import, to literally 804 00:39:58,380 --> 00:40:01,110 say from functions import a square function, 805 00:40:01,110 --> 00:40:05,410 import a particular name that is defined inside of functions.py. 806 00:40:05,410 --> 00:40:09,600 Another way I could have done this is just to say import functions, just 807 00:40:09,600 --> 00:40:11,400 import that whole module. 808 00:40:11,400 --> 00:40:13,770 But then I would need to say-- instead of just square, 809 00:40:13,770 --> 00:40:19,290 I would need to say functions.square, to mean go inside the functions module, 810 00:40:19,290 --> 00:40:22,770 and get the square function, and run that function. 811 00:40:22,770 --> 00:40:25,512 And this would operate in exactly the same way. 812 00:40:25,512 --> 00:40:26,970 So, a couple of different options-- 813 00:40:26,970 --> 00:40:29,790 I either import the entire module, in which case 814 00:40:29,790 --> 00:40:34,260 I use this dot notation to, say, access a particular part of that module. 815 00:40:34,260 --> 00:40:37,680 Or I say from functions import square to just 816 00:40:37,680 --> 00:40:42,180 import the name square into this file entirely so that I can just 817 00:40:42,180 --> 00:40:45,210 use the word square whenever I want to. 818 00:40:45,210 --> 00:40:48,300 And this works not just for modules that we have written, 819 00:40:48,300 --> 00:40:51,150 but also Python comes with the number of built-in modules. 820 00:40:51,150 --> 00:40:54,000 If you want to write programs that interact with CSV files, which 821 00:40:54,000 --> 00:40:58,350 are a spreadsheet file format, I can import Python's built-in CSV module 822 00:40:58,350 --> 00:41:00,970 to get access to a whole bunch of CSV-related features. 823 00:41:00,970 --> 00:41:02,970 There are a whole bunch of math-related features 824 00:41:02,970 --> 00:41:06,160 you can get by importing the math module, so on and so forth. 825 00:41:06,160 --> 00:41:08,610 And there are additional Python modules and packages 826 00:41:08,610 --> 00:41:11,140 that you can install that other people have written. 827 00:41:11,140 --> 00:41:13,290 And then you just import them when the time comes. 828 00:41:13,290 --> 00:41:16,598 And next time, as we take a look at Django, this is one of the techniques 829 00:41:16,598 --> 00:41:18,390 that we're going to be looking at, is using 830 00:41:18,390 --> 00:41:23,550 functions that have been written by people that are not ourselves. 831 00:41:23,550 --> 00:41:26,100 So that now is modules and how we can use 832 00:41:26,100 --> 00:41:30,210 modules to be able to import functions in order to allow for certain behavior. 833 00:41:30,210 --> 00:41:33,870 And this is one way that we can program using the Python programming language. 834 00:41:33,870 --> 00:41:35,798 But another key technique that Python supports 835 00:41:35,798 --> 00:41:38,340 that are supported by a number of other programming languages 836 00:41:38,340 --> 00:41:43,050 as well is an idea of object-oriented programming, a special type 837 00:41:43,050 --> 00:41:46,030 of programming or programming paradigm, so to speak, 838 00:41:46,030 --> 00:41:48,900 which is a way of thinking about the way that we write programs. 839 00:41:48,900 --> 00:41:50,940 In an object-oriented programming, we think 840 00:41:50,940 --> 00:41:53,730 about the world in terms of objects where 841 00:41:53,730 --> 00:41:57,300 objects might store information, store some data inside of them, 842 00:41:57,300 --> 00:42:01,050 and also support the ability to perform types of operations, 843 00:42:01,050 --> 00:42:04,830 some sort of actions, or methods, or functions, as we might call them, 844 00:42:04,830 --> 00:42:07,720 that can operate on those objects. 845 00:42:07,720 --> 00:42:11,700 So now we're going to take a look at some of the object-oriented capacities 846 00:42:11,700 --> 00:42:15,150 that the Python programming language is going to give us the ability to have. 847 00:42:15,150 --> 00:42:17,640 So, Python comes with a number of built in types. 848 00:42:17,640 --> 00:42:19,290 It has types for lists. 849 00:42:19,290 --> 00:42:21,880 It has types for sets and so on and so forth. 850 00:42:21,880 --> 00:42:25,380 Let's imagine, though, that we want to create a new type in Python, 851 00:42:25,380 --> 00:42:29,170 some way of representing other types of data. 852 00:42:29,170 --> 00:42:31,860 For example, two-dimensional points, things 853 00:42:31,860 --> 00:42:35,120 we've talked about before-- something that has an x value and a y value. 854 00:42:35,120 --> 00:42:36,870 Now, as we've already discussed, you could 855 00:42:36,870 --> 00:42:40,710 do this using a tuple, just using one number comma another number. 856 00:42:40,710 --> 00:42:44,280 But we could create an entire class of objects 857 00:42:44,280 --> 00:42:47,127 to be able to represent this data structure as well. 858 00:42:47,127 --> 00:42:48,960 And so that's what we'll take a look at now, 859 00:42:48,960 --> 00:42:52,200 is how to create a class in Python. 860 00:42:52,200 --> 00:42:55,860 So I'll create a new file called classes.py. 861 00:42:55,860 --> 00:42:58,920 And all a class is, is you can think of a class 862 00:42:58,920 --> 00:43:01,530 as a template for a type of object. 863 00:43:01,530 --> 00:43:05,460 We are going to define a new class called Point. 864 00:43:05,460 --> 00:43:08,340 And then after we've defined what a point is, 865 00:43:08,340 --> 00:43:10,650 we will be able to create other points. 866 00:43:10,650 --> 00:43:15,760 We'll be able to create points to store x and y values, for example. 867 00:43:15,760 --> 00:43:18,060 And so what do we need in order to create a class? 868 00:43:18,060 --> 00:43:22,820 Well, we need some way to say that when I create a point, what should happen? 869 00:43:22,820 --> 00:43:24,930 And in Python, this is defined using what's 870 00:43:24,930 --> 00:43:29,700 called a magic method called underscore underscore init. 871 00:43:29,700 --> 00:43:33,510 And underscore underscore init is a method or function that 872 00:43:33,510 --> 00:43:36,210 is going to automatically be called every time that I 873 00:43:36,210 --> 00:43:38,940 try to create a new point. 874 00:43:38,940 --> 00:43:42,000 And this function takes a couple of arguments. 875 00:43:42,000 --> 00:43:46,530 All functions that operate on objects themselves, otherwise known as methods, 876 00:43:46,530 --> 00:43:49,920 are going to take the first argument called self. 877 00:43:49,920 --> 00:43:54,330 And this argument self represents the object in question. 878 00:43:54,330 --> 00:43:56,700 And this is going to be important because we don't just 879 00:43:56,700 --> 00:44:00,210 want a single variable called x to store the points x coordinate 880 00:44:00,210 --> 00:44:03,240 or a single variable called y to store the y coordinate 881 00:44:03,240 --> 00:44:07,528 because two different points might have different x and different y values. 882 00:44:07,528 --> 00:44:09,570 And we want to be able to store those separately. 883 00:44:09,570 --> 00:44:13,360 And we're going to store them inside of the object itself. 884 00:44:13,360 --> 00:44:16,842 So this variable self references the object 885 00:44:16,842 --> 00:44:18,300 that we are currently dealing with. 886 00:44:18,300 --> 00:44:20,490 And it might change depending on which point we 887 00:44:20,490 --> 00:44:23,790 happen to be interacting with at any given time. 888 00:44:23,790 --> 00:44:25,530 What other inputs does a point need? 889 00:44:25,530 --> 00:44:29,140 Well, a point also needs an x value and a y value. 890 00:44:29,140 --> 00:44:32,160 So when we create a point, we're going to provide to that point 891 00:44:32,160 --> 00:44:35,410 an x value and a y value. 892 00:44:35,410 --> 00:44:37,680 Now, what do we need to do in order to store 893 00:44:37,680 --> 00:44:40,170 all this data inside of the point? 894 00:44:40,170 --> 00:44:44,290 Well, recall that self is representing the point itself. 895 00:44:44,290 --> 00:44:46,850 And so if we want to store data inside of that point 896 00:44:46,850 --> 00:44:50,340 and allow that point to store its own x and y values, 897 00:44:50,340 --> 00:44:55,950 then we need to store that data inside of the self, so to speak. 898 00:44:55,950 --> 00:45:01,110 And in order to do that, we can use this dot notation to say self.x 899 00:45:01,110 --> 00:45:04,980 is equal to whatever this input x happens to be. 900 00:45:04,980 --> 00:45:10,950 And self.y is equal to whatever this argument y happens to be. 901 00:45:10,950 --> 00:45:13,290 And these values, x and y, they can be called anything. 902 00:45:13,290 --> 00:45:17,390 They could just be called like input one and input two, for example. 903 00:45:17,390 --> 00:45:19,140 And then you would just reflect them here. 904 00:45:19,140 --> 00:45:21,930 The important thing is that these two input values 905 00:45:21,930 --> 00:45:25,320 are being stored inside of the point itself 906 00:45:25,320 --> 00:45:28,440 in properties that we're going to call x and y. 907 00:45:28,440 --> 00:45:30,945 908 00:45:30,945 --> 00:45:32,820 All right, so that was a little bit abstract. 909 00:45:32,820 --> 00:45:35,160 But now let's see how we could actually use this. 910 00:45:35,160 --> 00:45:41,050 If I want to create a new point called p, I can say p equals point. 911 00:45:41,050 --> 00:45:44,375 And then the self argument is going to be provided automatically. 912 00:45:44,375 --> 00:45:45,750 I don't need to worry about that. 913 00:45:45,750 --> 00:45:48,330 But I do need to provide input one and input two-- 914 00:45:48,330 --> 00:45:51,220 the x value and the y value. 915 00:45:51,220 --> 00:45:54,900 So I'll go ahead and provide an x value of two and a y value of eight, 916 00:45:54,900 --> 00:45:56,230 for example. 917 00:45:56,230 --> 00:45:58,210 So now I've created this point. 918 00:45:58,210 --> 00:46:01,380 And now that I have a point, I can print out information about the point. 919 00:46:01,380 --> 00:46:03,660 I can print out the x value of the point. 920 00:46:03,660 --> 00:46:06,480 And I can print out the y value of the point. 921 00:46:06,480 --> 00:46:10,290 Again, I'm using this dot notation to say, go into the point 922 00:46:10,290 --> 00:46:13,440 and access data that is stored inside of that point. 923 00:46:13,440 --> 00:46:17,460 Access its x value and access its y value. 924 00:46:17,460 --> 00:46:22,380 So now when I run this program, Python classes.py, what I get 925 00:46:22,380 --> 00:46:25,530 is two on the first line, that is the x value, and then 926 00:46:25,530 --> 00:46:28,110 eight on the second-- or eight on the second line. 927 00:46:28,110 --> 00:46:30,340 That is the y value. 928 00:46:30,340 --> 00:46:32,310 So what we have here is a function called 929 00:46:32,310 --> 00:46:37,560 init that creates a point by storing the two inputs inside of the object, 930 00:46:37,560 --> 00:46:39,930 inside of a property called x and a property 931 00:46:39,930 --> 00:46:43,920 called y, such that later I can create a point which 932 00:46:43,920 --> 00:46:46,350 calls this init function implicitly. 933 00:46:46,350 --> 00:46:49,590 And after we've created the point, I can access the data inside of it. 934 00:46:49,590 --> 00:46:52,560 I can say print out whatever p.x is equal to, 935 00:46:52,560 --> 00:46:57,480 print out whatever p.y is equal to as well. 936 00:46:57,480 --> 00:47:00,150 So that was a fairly simple example of creating a class, 937 00:47:00,150 --> 00:47:04,450 just creating a class for representing a point, an x and a y value. 938 00:47:04,450 --> 00:47:06,190 Let's look at a more interesting example. 939 00:47:06,190 --> 00:47:09,148 Let's imagine that we're trying to write a program for an airline where 940 00:47:09,148 --> 00:47:12,292 the airline needs to keep track of booking passengers on a flight 941 00:47:12,292 --> 00:47:14,250 and making sure that no flight gets overbooked. 942 00:47:14,250 --> 00:47:16,190 We don't want more passengers on the flight 943 00:47:16,190 --> 00:47:19,260 than there is capacity on that flight. 944 00:47:19,260 --> 00:47:22,770 So let's define a new class that we're going to call flight. 945 00:47:22,770 --> 00:47:25,320 And this time, the init method is just going 946 00:47:25,320 --> 00:47:29,760 to take a single argument other than the self, which is the capacity. 947 00:47:29,760 --> 00:47:32,160 Every flight needs some sort of capacity to know 948 00:47:32,160 --> 00:47:34,690 how many people can fit on the plane. 949 00:47:34,690 --> 00:47:39,660 And so I'll store that inside of a value called self.capacity equals capacity. 950 00:47:39,660 --> 00:47:43,220 And what other information do we need to store about a flight? 951 00:47:43,220 --> 00:47:44,880 Well, a flight has a capacity. 952 00:47:44,880 --> 00:47:48,280 And it also has all of the passengers on the flight. 953 00:47:48,280 --> 00:47:50,520 And so we could represent this in a number of ways. 954 00:47:50,520 --> 00:47:54,850 But we know that lists can be used in order to store a sequence of values. 955 00:47:54,850 --> 00:47:57,000 So we'll go ahead and just create a list that 956 00:47:57,000 --> 00:48:02,890 will store in self.passengers that is going to be equal to the empty list. 957 00:48:02,890 --> 00:48:07,110 So we start out with an empty list of passengers. 958 00:48:07,110 --> 00:48:09,770 So now if I want to create a flight, I can 959 00:48:09,770 --> 00:48:14,030 say flight equals and then Flight, that's the name of the class, 960 00:48:14,030 --> 00:48:15,620 and then provide a capacity. 961 00:48:15,620 --> 00:48:19,400 I can say capacity of three to mean three people can go 962 00:48:19,400 --> 00:48:21,345 in this flight, but no more than three. 963 00:48:21,345 --> 00:48:23,720 That is the capacity because that is the argument that is 964 00:48:23,720 --> 00:48:25,852 specified inside of this init function. 965 00:48:25,852 --> 00:48:27,560 And when I do so, I'm automatically going 966 00:48:27,560 --> 00:48:31,780 to get this empty list of passengers. 967 00:48:31,780 --> 00:48:36,090 So now let's think about what methods, or what functions, 968 00:48:36,090 --> 00:48:39,690 we might care about performing when it comes to a flight. 969 00:48:39,690 --> 00:48:42,920 So one reasonable function to add would be a function that says, 970 00:48:42,920 --> 00:48:45,010 all right, let's add a passenger to the flight 971 00:48:45,010 --> 00:48:48,640 if I want someone new to go on the flight. 972 00:48:48,640 --> 00:48:50,960 So how might it go about doing that? 973 00:48:50,960 --> 00:48:53,830 Well, let's define a new method, also known as a function, 974 00:48:53,830 --> 00:48:57,580 to this flight class called Add Passenger. 975 00:48:57,580 --> 00:49:00,010 This method can be called whatever we want. 976 00:49:00,010 --> 00:49:03,160 Because this is a method that's going to work on an individual object, 977 00:49:03,160 --> 00:49:05,530 we need some way of referencing that object itself. 978 00:49:05,530 --> 00:49:07,900 So we'll use the keyword self again. 979 00:49:07,900 --> 00:49:11,600 And when we add a passenger, we need to add a passenger by their name. 980 00:49:11,600 --> 00:49:17,530 So I need to specify their name as well, such that now here, I 981 00:49:17,530 --> 00:49:21,670 want to add that name to the passengers list. 982 00:49:21,670 --> 00:49:24,040 How do I get access to the passengers list? 983 00:49:24,040 --> 00:49:26,980 Well, I have access to the self, the object of itself. 984 00:49:26,980 --> 00:49:30,130 And I store the passengers inside of self, 985 00:49:30,130 --> 00:49:34,780 in self.passenger, an attribute of this object. 986 00:49:34,780 --> 00:49:39,200 And self.passenger is a list that initially starts out as an empty list. 987 00:49:39,200 --> 00:49:41,860 But if I want to add something to the end of the list, 988 00:49:41,860 --> 00:49:43,940 we've already seen that in order to do that, 989 00:49:43,940 --> 00:49:48,620 I can say self-passengers.append name. 990 00:49:48,620 --> 00:49:54,300 So that adds in someone new to the end of this passengers list. 991 00:49:54,300 --> 00:49:56,910 Now, what could potentially go wrong here? 992 00:49:56,910 --> 00:50:00,060 Well, every time we call this Add Passenger function, what's 993 00:50:00,060 --> 00:50:03,200 going to happen is we are going to append to the end of this passengers 994 00:50:03,200 --> 00:50:04,980 list this name. 995 00:50:04,980 --> 00:50:09,030 But we haven't taken into consideration the capacity of the flight. 996 00:50:09,030 --> 00:50:11,880 Ideally, our Add Passengers function shouldn't 997 00:50:11,880 --> 00:50:17,468 let someone be added to a flight if the flight is already at capacity. 998 00:50:17,468 --> 00:50:19,510 So there are a number of things we could do here. 999 00:50:19,510 --> 00:50:21,570 We could just check it inside of this function. 1000 00:50:21,570 --> 00:50:25,290 But just for good measure, let's create a new function. 1001 00:50:25,290 --> 00:50:29,790 Let's add a new function called Open Seats that 1002 00:50:29,790 --> 00:50:34,600 is going to return the number of open seats that are on the plane. 1003 00:50:34,600 --> 00:50:36,370 Other than Self, there are no other inputs 1004 00:50:36,370 --> 00:50:38,710 that we need to calculate how many open seats there are. 1005 00:50:38,710 --> 00:50:41,890 The only thing we need to know in order to calculate open seats 1006 00:50:41,890 --> 00:50:48,290 is we need to know the capacity minus however many passengers there are. 1007 00:50:48,290 --> 00:50:52,040 Remember, self.passengers is our list of all the passengers. 1008 00:50:52,040 --> 00:50:55,100 And any time we have a sequence to get the length of that sequence, 1009 00:50:55,100 --> 00:50:58,430 I can say len, or length of that sequence, 1010 00:50:58,430 --> 00:51:02,490 to say get me the number of passengers that there are. 1011 00:51:02,490 --> 00:51:05,060 So now we have this function called Open Seats, which 1012 00:51:05,060 --> 00:51:08,330 will return capacity minus the number of passengers 1013 00:51:08,330 --> 00:51:12,710 and tell us how many open seats there are. 1014 00:51:12,710 --> 00:51:16,880 And now in this Add Passenger function, I can add some additional logic. 1015 00:51:16,880 --> 00:51:22,160 I can say if not self.open_seats. 1016 00:51:22,160 --> 00:51:24,920 1017 00:51:24,920 --> 00:51:27,470 So this is equivalent to me saying in this case, like, 1018 00:51:27,470 --> 00:51:32,340 if self.open_seats equals equals zero, meaning there are no open seats, 1019 00:51:32,340 --> 00:51:36,560 a more Pythonic way, so to speak, of expressing this idea is just saying 1020 00:51:36,560 --> 00:51:38,180 if not self.open_seats. 1021 00:51:38,180 --> 00:51:42,600 In other words, if there aren't any more open seats, then what should we do? 1022 00:51:42,600 --> 00:51:43,850 We should return. 1023 00:51:43,850 --> 00:51:47,420 And maybe you might imagine this Add Passenger function returns true 1024 00:51:47,420 --> 00:51:51,330 if it was able to successfully add a passenger and false otherwise. 1025 00:51:51,330 --> 00:51:54,080 So in this case, I can return false to say, you know what? 1026 00:51:54,080 --> 00:51:55,460 There aren't enough open seats. 1027 00:51:55,460 --> 00:51:57,950 Let me return false from the function to indicate 1028 00:51:57,950 --> 00:52:00,550 that there was some sort of error. 1029 00:52:00,550 --> 00:52:03,610 But otherwise, if there are open seats, we can add the passenger 1030 00:52:03,610 --> 00:52:06,760 and return true to mean that everything was OK, 1031 00:52:06,760 --> 00:52:10,867 we were able to add the passenger successfully. 1032 00:52:10,867 --> 00:52:12,450 So now we have these three functions-- 1033 00:52:12,450 --> 00:52:15,030 Init that creates a new flight, Add Passenger 1034 00:52:15,030 --> 00:52:17,220 that adds a new passenger to that flight, 1035 00:52:17,220 --> 00:52:20,560 and Open Seats, which tells us how many open seats there are. 1036 00:52:20,560 --> 00:52:23,340 And now let's use those functions to actually add 1037 00:52:23,340 --> 00:52:25,860 some passengers to this flight. 1038 00:52:25,860 --> 00:52:27,240 Let me get a list of people. 1039 00:52:27,240 --> 00:52:32,700 We'll say Harry, Ron, Hermione, and Ginny. 1040 00:52:32,700 --> 00:52:35,340 And now let me loop over all of those people. 1041 00:52:35,340 --> 00:52:42,554 For every person in that list of people, let's try to flight.add_passenger 1042 00:52:42,554 --> 00:52:44,410 person. 1043 00:52:44,410 --> 00:52:48,770 And we can save the result in a variable called success, for example. 1044 00:52:48,770 --> 00:52:51,350 And then I can say if success, well, then 1045 00:52:51,350 --> 00:52:59,460 let's print out that we added the person to flight successfully. 1046 00:52:59,460 --> 00:53:07,740 But else, otherwise, let's print out no available seats for that person. 1047 00:53:07,740 --> 00:53:08,990 So what's going on here? 1048 00:53:08,990 --> 00:53:11,120 We have a list of people, four people. 1049 00:53:11,120 --> 00:53:14,180 And for each of those people, we're going to try and add the passenger 1050 00:53:14,180 --> 00:53:16,940 to the flight calling flight.add_passenger, 1051 00:53:16,940 --> 00:53:20,450 calling this method, passing, as input, the person's name, 1052 00:53:20,450 --> 00:53:24,440 and save the result true or false in this variable called Success. 1053 00:53:24,440 --> 00:53:28,160 If success is true, we print out we've added them successfully. 1054 00:53:28,160 --> 00:53:32,880 Otherwise, we print out there are no available seats for that person. 1055 00:53:32,880 --> 00:53:35,840 So now we can try running this program. 1056 00:53:35,840 --> 00:53:38,800 I'll run Python classes.py. 1057 00:53:38,800 --> 00:53:41,800 And now we see we've added Harry, Ron, and Hermione to the flight 1058 00:53:41,800 --> 00:53:42,790 successfully. 1059 00:53:42,790 --> 00:53:45,400 But the flight had a capacity of three, which 1060 00:53:45,400 --> 00:53:48,700 means there are no available seats for Ginny, which we get as the error 1061 00:53:48,700 --> 00:53:50,587 message on the fourth line. 1062 00:53:50,587 --> 00:53:52,420 But if you're really trying to optimize, you 1063 00:53:52,420 --> 00:53:54,910 might notice you don't really need this variable. 1064 00:53:54,910 --> 00:53:56,800 I could just take this entire expression, 1065 00:53:56,800 --> 00:54:01,180 flight.add_passenger person, and put it in the condition itself. 1066 00:54:01,180 --> 00:54:03,670 I can say, try and add a passenger. 1067 00:54:03,670 --> 00:54:06,140 Add passenger will return true or false. 1068 00:54:06,140 --> 00:54:09,130 And if it returns true, that means it was a success. 1069 00:54:09,130 --> 00:54:12,460 And then I can print out that we've added the person to the flight 1070 00:54:12,460 --> 00:54:14,430 successfully. 1071 00:54:14,430 --> 00:54:17,130 So that is a brief look at object-oriented programming, 1072 00:54:17,130 --> 00:54:19,800 this technique within Python and other programming languages 1073 00:54:19,800 --> 00:54:23,040 to represent objects like this particular flight 1074 00:54:23,040 --> 00:54:26,550 and then to manipulate those objects using methods like the Add Passenger 1075 00:54:26,550 --> 00:54:29,490 method that takes a flight and adds people to it, 1076 00:54:29,490 --> 00:54:32,640 at least as long as there is available capacity on that flight. 1077 00:54:32,640 --> 00:54:34,860 It's one of the many powerful features of Python 1078 00:54:34,860 --> 00:54:37,440 that we'll be definitely taking a look at later in the term 1079 00:54:37,440 --> 00:54:41,522 and using as we go about building these web applications. 1080 00:54:41,522 --> 00:54:43,230 Now, there are a couple of final examples 1081 00:54:43,230 --> 00:54:45,438 that are just worth taking a look at just to give you 1082 00:54:45,438 --> 00:54:49,350 some exposure to some of the other features that are available in Python. 1083 00:54:49,350 --> 00:54:53,100 One thing that will be coming up soon is the idea of decorators. 1084 00:54:53,100 --> 00:54:56,070 And just as we can take a value in Python like a number 1085 00:54:56,070 --> 00:55:00,360 and modify the value, decorators are a way in Python of taking a function, 1086 00:55:00,360 --> 00:55:04,870 and modifying that function, adding some additional behavior to that function. 1087 00:55:04,870 --> 00:55:08,520 So I'll create a new file called decorators.py just 1088 00:55:08,520 --> 00:55:10,830 to demonstrate what we can do with decorators. 1089 00:55:10,830 --> 00:55:13,350 And the idea of a decorator is a decorator 1090 00:55:13,350 --> 00:55:17,070 is going to be a function that takes a function of input 1091 00:55:17,070 --> 00:55:20,910 and returns a modified version of that function as output. 1092 00:55:20,910 --> 00:55:24,540 So unlike other programming languages where functions just exist on their own 1093 00:55:24,540 --> 00:55:28,380 and they can't be passed in as input or output to other functions, in Python, 1094 00:55:28,380 --> 00:55:30,420 a function is just a value like any other. 1095 00:55:30,420 --> 00:55:32,610 You can pass it as input to another function. 1096 00:55:32,610 --> 00:55:35,250 You can get it as the output of another function. 1097 00:55:35,250 --> 00:55:37,980 And this is known as a functional programming paradigm, 1098 00:55:37,980 --> 00:55:41,560 where functions are themselves values. 1099 00:55:41,560 --> 00:55:46,470 So let's create a function that modifies another function by announcing 1100 00:55:46,470 --> 00:55:49,950 that the function is about to run and that the function has completed run, 1101 00:55:49,950 --> 00:55:51,270 just to demonstrate. 1102 00:55:51,270 --> 00:55:55,310 So this Announce function will take, as input, a function f. 1103 00:55:55,310 --> 00:55:57,780 And it's going to return a new function. 1104 00:55:57,780 --> 00:56:01,020 And usually, this function wraps up this function 1105 00:56:01,020 --> 00:56:03,960 f with some additional behavior, and for that reason, 1106 00:56:03,960 --> 00:56:05,760 is often called a wrapper function. 1107 00:56:05,760 --> 00:56:09,420 So we may call this wrapper to say that, all right, what 1108 00:56:09,420 --> 00:56:11,160 is my wrapper function going to do? 1109 00:56:11,160 --> 00:56:14,588 It's first going to print about to run the function just 1110 00:56:14,588 --> 00:56:16,630 to announce that we're about to run the function. 1111 00:56:16,630 --> 00:56:19,470 That's what I want my Announce decorator to do. 1112 00:56:19,470 --> 00:56:22,110 Then let's actually run the function f. 1113 00:56:22,110 --> 00:56:26,670 And then let's print done with the function. 1114 00:56:26,670 --> 00:56:30,300 So what my Announce decorator is doing is it's taking the function f 1115 00:56:30,300 --> 00:56:34,320 and it's creating a new function that just announces, via a print statement, 1116 00:56:34,320 --> 00:56:37,560 before and after the function is done running. 1117 00:56:37,560 --> 00:56:40,620 And then at the end, we'll return this new function, 1118 00:56:40,620 --> 00:56:42,910 which is the wrapper function. 1119 00:56:42,910 --> 00:56:45,970 So this right here is what we might call a decorator, a function that 1120 00:56:45,970 --> 00:56:49,930 takes a function, modifies it by adding some additional capabilities to it, 1121 00:56:49,930 --> 00:56:52,940 and then gives us back some output. 1122 00:56:52,940 --> 00:56:56,800 So now here, I can define a function called Hello that just prints "hello, 1123 00:56:56,800 --> 00:56:58,870 world," for example. 1124 00:56:58,870 --> 00:57:01,940 And then to add a decorator, I use the at symbol. 1125 00:57:01,940 --> 00:57:08,370 I can say at announce to say add the Announce decorator to this function. 1126 00:57:08,370 --> 00:57:10,320 And then I'll just run the function Hello. 1127 00:57:10,320 --> 00:57:12,340 And we'll see what happens. 1128 00:57:12,340 --> 00:57:15,012 I'll run Python decorators.py. 1129 00:57:15,012 --> 00:57:19,950 And I see about to run the function, then "hello, world," then done 1130 00:57:19,950 --> 00:57:21,183 with the function. 1131 00:57:21,183 --> 00:57:22,350 So again, why did that work? 1132 00:57:22,350 --> 00:57:25,980 It's because our Hello function that just printed 'hello, world" 1133 00:57:25,980 --> 00:57:28,770 is wrapped inside of this Announce decorator, 1134 00:57:28,770 --> 00:57:32,760 where what the Announce decorator does, is it takes our Hello function of input 1135 00:57:32,760 --> 00:57:36,450 and gets us a new function that first prints an alert warning that we're 1136 00:57:36,450 --> 00:57:39,330 about to run the function, actually runs the function, 1137 00:57:39,330 --> 00:57:41,310 and then prints another message. 1138 00:57:41,310 --> 00:57:43,230 So, a bit of a simple example here. 1139 00:57:43,230 --> 00:57:46,680 But there's a lot of power in decorators for being able to very quickly take 1140 00:57:46,680 --> 00:57:49,170 a function and add capability to it. 1141 00:57:49,170 --> 00:57:51,510 You might imagine in a web application, if you only 1142 00:57:51,510 --> 00:57:55,420 want certain functions to be able to run, if a user is logged in, 1143 00:57:55,420 --> 00:57:57,780 you can imagine writing a decorator that checks 1144 00:57:57,780 --> 00:58:00,060 to make sure that a user is logged in, and then just 1145 00:58:00,060 --> 00:58:03,450 using that decorator on all of the functions that you want to make sure 1146 00:58:03,450 --> 00:58:06,400 only work when a user so happens to be logged in. 1147 00:58:06,400 --> 00:58:09,660 So decorators are a very powerful tool that web application frameworks 1148 00:58:09,660 --> 00:58:12,930 like Django can make use of just to make the web application development 1149 00:58:12,930 --> 00:58:16,640 process a little bit easier as well. 1150 00:58:16,640 --> 00:58:21,070 Let's take a look at a couple other techniques that exist within Python. 1151 00:58:21,070 --> 00:58:25,940 One is how we might be able to more efficiently represent functions. 1152 00:58:25,940 --> 00:58:27,550 So let's imagine that I now have-- 1153 00:58:27,550 --> 00:58:31,610 I'm going to call this lambda.py for a reason you'll see in a moment. 1154 00:58:31,610 --> 00:58:35,110 Let's imagine that I have a list of names or people, for example. 1155 00:58:35,110 --> 00:58:39,790 And inside of this list of people, each person, instead of being just a string, 1156 00:58:39,790 --> 00:58:43,570 is going to be a dictionary that has both a name like Harry 1157 00:58:43,570 --> 00:58:46,810 and a house like Gryffindor. 1158 00:58:46,810 --> 00:58:51,610 And let me add another name like Cho and a house like Ravenclaw, 1159 00:58:51,610 --> 00:58:58,850 and then another name like Draco and a house like Slytherin. 1160 00:58:58,850 --> 00:59:02,300 So here we have a list where each of the elements inside of that list 1161 00:59:02,300 --> 00:59:04,490 is a dictionary, a mapping of keys and values. 1162 00:59:04,490 --> 00:59:05,600 And that's totally OK. 1163 00:59:05,600 --> 00:59:09,660 In Python, we have the ability to nest the data structures within one another. 1164 00:59:09,660 --> 00:59:12,290 We can have lists inside of other lists, or lists inside 1165 00:59:12,290 --> 00:59:15,860 of dictionaries, or in this case, dictionaries inside of a list. 1166 00:59:15,860 --> 00:59:17,960 And in fact, this nesting of data structures 1167 00:59:17,960 --> 00:59:20,420 is one of the reasons why it's very easy in Python 1168 00:59:20,420 --> 00:59:23,780 to be able to represent structured data like a list of people 1169 00:59:23,780 --> 00:59:26,900 where every person has various different properties. 1170 00:59:26,900 --> 00:59:30,860 What I might like to do now is something like sort all of these people 1171 00:59:30,860 --> 00:59:33,440 and then print them all out. 1172 00:59:33,440 --> 00:59:39,570 So I might want to say people.sort, and then print all the people. 1173 00:59:39,570 --> 00:59:42,730 But if I try to run this, I'll get an exception. 1174 00:59:42,730 --> 00:59:49,350 I get an exception, type error less than not supported between dict and dict, 1175 00:59:49,350 --> 00:59:52,990 which is sort of weird because I'm not using any less than symbol at all 1176 00:59:52,990 --> 00:59:54,152 anywhere in a program. 1177 00:59:54,152 --> 00:59:57,360 But in the trace-back, you'll see that the line of code that it's catching on 1178 00:59:57,360 --> 00:59:58,950 is people.sort. 1179 00:59:58,950 --> 01:00:02,070 Somehow, people.sort is causing a type error 1180 01:00:02,070 --> 01:00:06,630 because it's trying to use less than to compare two dictionaries. 1181 01:00:06,630 --> 01:00:09,090 And what this appears to mean is that Python doesn't 1182 01:00:09,090 --> 01:00:11,790 know how to sort these dictionaries. 1183 01:00:11,790 --> 01:00:14,280 It doesn't know, does Harry belong before or after Cho 1184 01:00:14,280 --> 01:00:18,090 because it doesn't know how to compare these two elements. 1185 01:00:18,090 --> 01:00:19,980 And so if I want to do something like this, 1186 01:00:19,980 --> 01:00:24,480 then I need to tell the sort function how to sort these people. 1187 01:00:24,480 --> 01:00:26,970 And so in order to do that, one way I could do this 1188 01:00:26,970 --> 01:00:30,810 is by defining a function that tells the sort function 1189 01:00:30,810 --> 01:00:33,480 how to do the sorting, what to look at when sorting. 1190 01:00:33,480 --> 01:00:36,780 So if I want to sort by people's name, let me define a function 1191 01:00:36,780 --> 01:00:39,750 that I'll just call f, that takes a person as input 1192 01:00:39,750 --> 01:00:43,800 and returns that person's name by looking up the name field 1193 01:00:43,800 --> 01:00:45,790 inside of the dictionary. 1194 01:00:45,790 --> 01:00:50,640 And now I can sort people by their name by saying sort key equals f. 1195 01:00:50,640 --> 01:00:52,680 What this means is sort all the people. 1196 01:00:52,680 --> 01:00:55,590 And the way to sort them, the way you know how to compare them, 1197 01:00:55,590 --> 01:00:59,670 is by running this function where this function takes a person 1198 01:00:59,670 --> 01:01:01,330 and gives us back their name. 1199 01:01:01,330 --> 01:01:03,580 And this will sort everyone by name. 1200 01:01:03,580 --> 01:01:06,690 Now, if I run Python lambda.py, you will see that I first 1201 01:01:06,690 --> 01:01:10,230 get Cho, then Draco, then Harry in alphabetical order 1202 01:01:10,230 --> 01:01:14,490 by name, whereas if instead I had tried to sort people by their house 1203 01:01:14,490 --> 01:01:19,020 by changing my function that I'm using to sort and then rerun this, now 1204 01:01:19,020 --> 01:01:21,690 I see that its first Harry who is in Gryffindor, then 1205 01:01:21,690 --> 01:01:24,320 Ravenclaw, then Slytherin, for example. 1206 01:01:24,320 --> 01:01:28,230 So we get the houses in alphabetical order instead. 1207 01:01:28,230 --> 01:01:31,560 But the reason I show this is because this function is so simple 1208 01:01:31,560 --> 01:01:33,330 and is only used in one place. 1209 01:01:33,330 --> 01:01:35,820 Python actually gives us an easier way to represent 1210 01:01:35,820 --> 01:01:40,510 a very short, one-line function using something called a lambda expression. 1211 01:01:40,510 --> 01:01:42,840 And this is a way of including the function just 1212 01:01:42,840 --> 01:01:45,150 as a single value on a single line. 1213 01:01:45,150 --> 01:01:49,500 I can say instead of defining a function called f, I can get rid of all of this 1214 01:01:49,500 --> 01:01:53,110 and just say, sort by this key, a lambda, 1215 01:01:53,110 --> 01:01:59,080 which is a function that takes a person and returns the person's name. 1216 01:01:59,080 --> 01:02:03,760 So we say person as the input, colon person name as the output. 1217 01:02:03,760 --> 01:02:06,090 This is a condensed way of saying the same thing we 1218 01:02:06,090 --> 01:02:09,390 saw a moment ago, of defining a function, giving it a name, 1219 01:02:09,390 --> 01:02:11,070 and then passing in the name here. 1220 01:02:11,070 --> 01:02:15,840 This right here is a complete function that takes a person as input 1221 01:02:15,840 --> 01:02:17,850 and returns their name. 1222 01:02:17,850 --> 01:02:22,350 So Python lambda.py, that will actually sort the people by their name-- 1223 01:02:22,350 --> 01:02:24,870 Cho, then Draco, then Harry. 1224 01:02:24,870 --> 01:02:29,580 Whereas if I have left off this key altogether and then tried to sort, 1225 01:02:29,580 --> 01:02:30,990 well then we get this type error. 1226 01:02:30,990 --> 01:02:34,140 Because we can't compare these two dictionaries. 1227 01:02:34,140 --> 01:02:37,110 So we've seen a lot of different exceptions now throughout Python. 1228 01:02:37,110 --> 01:02:39,240 So the very last example we'll take a look at 1229 01:02:39,240 --> 01:02:41,670 is an example of how to deal with these exceptions, 1230 01:02:41,670 --> 01:02:45,000 like what to do when things might go wrong if we want our program 1231 01:02:45,000 --> 01:02:49,860 to be able to handle those possible exceptional cases, situations where 1232 01:02:49,860 --> 01:02:52,660 things might, in fact, go wrong. 1233 01:02:52,660 --> 01:02:53,880 So let's try an example. 1234 01:02:53,880 --> 01:02:57,630 I'll create a new file that I'm going to call exceptions.py. 1235 01:02:57,630 --> 01:03:01,860 And what exceptions.py is going to do is it's going to get some input. 1236 01:03:01,860 --> 01:03:05,970 It's going to say let's get an integer input called x. 1237 01:03:05,970 --> 01:03:09,150 And let's get an integer input called y. 1238 01:03:09,150 --> 01:03:13,200 And then it lets go ahead and print out the result of x divided by y. 1239 01:03:13,200 --> 01:03:15,960 So result equals x divided by y. 1240 01:03:15,960 --> 01:03:23,980 And then let's print out something like x divided by y equals result. 1241 01:03:23,980 --> 01:03:28,022 And we can literally print out the values of x and y. 1242 01:03:28,022 --> 01:03:30,730 So this is a simple program that's just performing some division. 1243 01:03:30,730 --> 01:03:34,030 Get a value of x, get a value of y, divide the two, 1244 01:03:34,030 --> 01:03:37,630 and print out the result. We can try running this by running Python 1245 01:03:37,630 --> 01:03:41,980 exceptions.py if I would type in like five and then 10, 1246 01:03:41,980 --> 01:03:44,470 five divided by 10 is 0.5-- 1247 01:03:44,470 --> 01:03:46,620 exactly what I might expect. 1248 01:03:46,620 --> 01:03:48,080 But what could go wrong now? 1249 01:03:48,080 --> 01:03:51,850 You remember from math in division, what could go wrong is if I type in five 1250 01:03:51,850 --> 01:03:55,720 and then zero, try and do five divided by zero, what's going to happen? 1251 01:03:55,720 --> 01:03:57,610 Well, when I do that, I get an exception. 1252 01:03:57,610 --> 01:04:00,310 I get a zero division error, which is an error that happens 1253 01:04:00,310 --> 01:04:02,898 whenever you try to divide by zero. 1254 01:04:02,898 --> 01:04:04,690 What I'd like to happen though in this case 1255 01:04:04,690 --> 01:04:08,170 is not for my program to display kind of a messy error and a trace-back 1256 01:04:08,170 --> 01:04:11,560 like this, but to handle the exception gracefully, so to speak. 1257 01:04:11,560 --> 01:04:15,400 To be able to catch when the user does something wrong 1258 01:04:15,400 --> 01:04:18,670 and report a nicer looking message instead. 1259 01:04:18,670 --> 01:04:20,540 And so how might I go about doing that. 1260 01:04:20,540 --> 01:04:25,255 Well, one thing I can do here is instead of just saying result equals x over y, 1261 01:04:25,255 --> 01:04:32,020 I can say try to do this, try to set result equal to x divided by y, 1262 01:04:32,020 --> 01:04:36,790 and then say except if a zero division error happens. 1263 01:04:36,790 --> 01:04:38,240 Then let's do something else. 1264 01:04:38,240 --> 01:04:44,713 Let's print error cannot divide by zero, and then exit the program. 1265 01:04:44,713 --> 01:04:45,880 How do you exit the program? 1266 01:04:45,880 --> 01:04:49,420 It turns out there's a module in Python called sys. 1267 01:04:49,420 --> 01:04:55,170 And if I import the sys module, I can say sys.exit1 1268 01:04:55,170 --> 01:04:58,990 to mean exit the program with a status code of one, where a status code of one 1269 01:04:58,990 --> 01:05:02,470 generally means something went wrong in this program. 1270 01:05:02,470 --> 01:05:05,350 So now I'm trying to divide-- x divided by y-- 1271 01:05:05,350 --> 01:05:08,170 except I have an exception handler. 1272 01:05:08,170 --> 01:05:09,790 This is a try-except expression. 1273 01:05:09,790 --> 01:05:13,540 I'm saying try to do this except if this exception happens, rather than have 1274 01:05:13,540 --> 01:05:17,980 the program crash, just print out this error message, can't divide by zero, 1275 01:05:17,980 --> 01:05:20,280 and then exit the program. 1276 01:05:20,280 --> 01:05:21,805 So now let's try it-- 1277 01:05:21,805 --> 01:05:22,680 Python exceptions.py. 1278 01:05:22,680 --> 01:05:27,880 Again, five and 10 works totally normally, gets me a value of 0.5. 1279 01:05:27,880 --> 01:05:31,920 But now if I try five and zero, press Return, I get an error. 1280 01:05:31,920 --> 01:05:33,165 Cannot divide by zero-- 1281 01:05:33,165 --> 01:05:35,790 no long exception that's going to look complicated to the user. 1282 01:05:35,790 --> 01:05:37,020 It's no longer messy. 1283 01:05:37,020 --> 01:05:40,350 I've been able to handle the exception gracefully. 1284 01:05:40,350 --> 01:05:43,980 Now, one other exception that might come up is what if instead of x is five, 1285 01:05:43,980 --> 01:05:48,000 I type in a word like "hello," something that's not a number. 1286 01:05:48,000 --> 01:05:51,970 Now I get another type of exception, a value error, 1287 01:05:51,970 --> 01:05:55,060 which is happening when I try and convert something to an int 1288 01:05:55,060 --> 01:05:58,740 because Hello cannot be converted into a base 10 integer. 1289 01:05:58,740 --> 01:06:02,230 You can't take text that is not a number and turn it into an integer. 1290 01:06:02,230 --> 01:06:05,610 So instead, I'm getting this value error here. 1291 01:06:05,610 --> 01:06:06,783 How can I deal with that? 1292 01:06:06,783 --> 01:06:08,700 Well, I can deal with it in much the same way. 1293 01:06:08,700 --> 01:06:13,080 When I'm getting this input x and y, I can say rather than just get the input, 1294 01:06:13,080 --> 01:06:16,030 just try to get the input. 1295 01:06:16,030 --> 01:06:20,020 Except if a value error happens, which is the area that we got a moment ago, 1296 01:06:20,020 --> 01:06:25,660 this value error, then print error invalid input, 1297 01:06:25,660 --> 01:06:28,890 and go ahead and sys.exit1. 1298 01:06:28,890 --> 01:06:31,050 So now I've been able to handle that error as well. 1299 01:06:31,050 --> 01:06:33,390 I can say Python exceptions.py. 1300 01:06:33,390 --> 01:06:35,280 I can say Hello. 1301 01:06:35,280 --> 01:06:37,170 And I just get error invalid input. 1302 01:06:37,170 --> 01:06:38,580 I can divide by zero. 1303 01:06:38,580 --> 01:06:40,620 I get error cannot divide by zero. 1304 01:06:40,620 --> 01:06:43,120 But if I do type of valid x and a y value, 1305 01:06:43,120 --> 01:06:46,840 then I get the result of dividing one number by the other. 1306 01:06:46,840 --> 01:06:49,050 So exception handling is often a helpful tool 1307 01:06:49,050 --> 01:06:51,810 for if you expect that some lines of code you might be running 1308 01:06:51,810 --> 01:06:55,110 might run into some sort of problem, be they a value error, or a zero division 1309 01:06:55,110 --> 01:06:57,180 error, or some other error altogether, to be 1310 01:06:57,180 --> 01:06:59,100 able to handle those errors gracefully. 1311 01:06:59,100 --> 01:07:00,892 And that's probably what you want if you're 1312 01:07:00,892 --> 01:07:03,240 going about building a web application using Python, 1313 01:07:03,240 --> 01:07:05,737 is the ability to say that if something goes wrong, 1314 01:07:05,737 --> 01:07:08,070 we want to handle the error nicely, display a nice error 1315 01:07:08,070 --> 01:07:10,950 message to the user telling them what was wrong instead 1316 01:07:10,950 --> 01:07:13,613 of having the program entirely crash. 1317 01:07:13,613 --> 01:07:16,530 So those are some of the key features now with this Python programming 1318 01:07:16,530 --> 01:07:19,110 languagem this language that gives us the ability 1319 01:07:19,110 --> 01:07:22,650 to define these functions, and loops, and conditions in very convenient ways, 1320 01:07:22,650 --> 01:07:26,520 to create classes where we can begin to build objects that are able to perform 1321 01:07:26,520 --> 01:07:28,260 various different types of tasks. 1322 01:07:28,260 --> 01:07:32,580 And next time using Python, we'll be able to design web applications such 1323 01:07:32,580 --> 01:07:35,310 that users are able to make requests to our web applications 1324 01:07:35,310 --> 01:07:37,720 and get some sort of response back. 1325 01:07:37,720 --> 01:07:40,370 So we will see you next time. 1326 01:07:40,370 --> 01:07:41,000