1 00:00:00,000 --> 00:00:11,702 2 00:00:11,702 --> 00:00:13,660 BRIAN YU: We'll go ahead and get started today. 3 00:00:13,660 --> 00:00:17,080 Welcome back, everyone, to the second day of CS50 Beyond. 4 00:00:17,080 --> 00:00:20,110 So for just a recap for those of you who weren't here yesterday, 5 00:00:20,110 --> 00:00:23,140 or just as a refresher, yesterday we introduced 6 00:00:23,140 --> 00:00:26,260 the world of building web pages, looking at HTML and CSS, 7 00:00:26,260 --> 00:00:29,470 diving a little bit beyond what CS50 originally taught, 8 00:00:29,470 --> 00:00:31,660 looking at things like mobile responsiveness, things 9 00:00:31,660 --> 00:00:35,140 like media queries for determining how styling should look on a big screen 10 00:00:35,140 --> 00:00:37,900 or on a small screen, looking at SaaS, a technology 11 00:00:37,900 --> 00:00:41,580 we can use to generate CSS code based on variables 12 00:00:41,580 --> 00:00:44,740 and nesting and other different, more advanced features that CSS by itself 13 00:00:44,740 --> 00:00:45,610 doesn't offer. 14 00:00:45,610 --> 00:00:48,820 We looked at different features of HTML5, more advanced ideas 15 00:00:48,820 --> 00:00:50,880 like the data list for doing auto completion. 16 00:00:50,880 --> 00:00:52,630 We looked at regular expressions which are 17 00:00:52,630 --> 00:00:56,830 ways of using a pattern to define a set of strings that 18 00:00:56,830 --> 00:00:59,890 are of accepted inputs, for instance, that you can use in an input 19 00:00:59,890 --> 00:01:02,765 field as a pattern when you're trying to validate some sort of input, 20 00:01:02,765 --> 00:01:03,650 for instance. 21 00:01:03,650 --> 00:01:07,720 And then we also took a look at Git, a version control software 22 00:01:07,720 --> 00:01:11,080 that we can use to track changes to code, keep track of modifications 23 00:01:11,080 --> 00:01:13,840 so that we can go back, branch off, and try different things. 24 00:01:13,840 --> 00:01:16,240 So we covered a lot of topics yesterday. 25 00:01:16,240 --> 00:01:18,370 Any high level questions about yesterday's 26 00:01:18,370 --> 00:01:20,590 topics before we dive into today? 27 00:01:20,590 --> 00:01:22,480 If you're having specific technical problems, 28 00:01:22,480 --> 00:01:24,520 feel free to flag down a staff member during project time. 29 00:01:24,520 --> 00:01:26,020 We're definitely happy to help you with that. 30 00:01:26,020 --> 00:01:29,230 But questions about anything as you were thinking about these ideas yesterday 31 00:01:29,230 --> 00:01:31,609 that didn't come up? 32 00:01:31,609 --> 00:01:34,400 OK, well, definitely feel free to bring them up if they do come up. 33 00:01:34,400 --> 00:01:38,750 Goal of today is going to be to explore, moving forward, web application 34 00:01:38,750 --> 00:01:40,800 design with Python and Flask. 35 00:01:40,800 --> 00:01:43,850 So Python and Flask are both ideas that we saw in CS50-- 36 00:01:43,850 --> 00:01:46,910 Python being the language that we were using to build web applications-- 37 00:01:46,910 --> 00:01:49,910 but also, more generally, a very useful practical programming language 38 00:01:49,910 --> 00:01:51,470 that's quite popular nowadays. 39 00:01:51,470 --> 00:01:53,630 And then Flask being a framework in Python 40 00:01:53,630 --> 00:01:57,600 that we can use in order to build web applications easily, efficiently, 41 00:01:57,600 --> 00:01:58,500 and effectively. 42 00:01:58,500 --> 00:01:59,869 So we saw both of them in CS50. 43 00:01:59,869 --> 00:02:02,660 We'll do a bit of review of them in case you're a bit rusty on them 44 00:02:02,660 --> 00:02:04,190 in order to be a bit of a refresher. 45 00:02:04,190 --> 00:02:07,040 We'll also look at some more advanced and more sophisticated 46 00:02:07,040 --> 00:02:08,449 techniques and concepts. 47 00:02:08,449 --> 00:02:11,089 Definitely feel free to stop me at any point with questions. 48 00:02:11,089 --> 00:02:13,880 And of course, if you go to the course website as you did yesterday 49 00:02:13,880 --> 00:02:16,730 and click on that feedback link, and just have that open on your computer, 50 00:02:16,730 --> 00:02:19,063 definitely feel free to use that as a feedback mechanism 51 00:02:19,063 --> 00:02:20,725 today as we go through today's topics. 52 00:02:20,725 --> 00:02:22,850 If things are making sense, press the green button. 53 00:02:22,850 --> 00:02:25,220 If things aren't making sense, press the red button. 54 00:02:25,220 --> 00:02:26,480 That just lets me know-- 55 00:02:26,480 --> 00:02:29,660 perfect-- that you're following along with things that I'm saying 56 00:02:29,660 --> 00:02:32,000 or if you need some clarification, need me to slow down, 57 00:02:32,000 --> 00:02:34,210 or explain something in a slightly different way. 58 00:02:34,210 --> 00:02:35,960 Structure of the day is going to be pretty 59 00:02:35,960 --> 00:02:37,820 similar to what we did yesterday. 60 00:02:37,820 --> 00:02:41,130 We'll have some morning time to talk about Python and Flask web application 61 00:02:41,130 --> 00:02:41,630 development. 62 00:02:41,630 --> 00:02:42,980 I'll provide some examples. 63 00:02:42,980 --> 00:02:44,360 Then we'll have a bit of a morning project. 64 00:02:44,360 --> 00:02:46,240 This one will be a little more structured than yesterday, 65 00:02:46,240 --> 00:02:49,580 where it was sort of free form and you could choose whatever you wanted to. 66 00:02:49,580 --> 00:02:52,047 We'll propose a project for you to attempt to try. 67 00:02:52,047 --> 00:02:55,130 We'll start it together so that you can get a sense for the basic building 68 00:02:55,130 --> 00:02:58,150 blocks, and then leave most of the features up to you to implement. 69 00:02:58,150 --> 00:03:01,400 And then later this afternoon we'll take a look at some other Python features, 70 00:03:01,400 --> 00:03:03,650 looking at the world of object oriented programming, 71 00:03:03,650 --> 00:03:06,858 another programming paradigm you might be familiar with from other languages, 72 00:03:06,858 --> 00:03:08,810 like Java for instance, taking a look at how 73 00:03:08,810 --> 00:03:11,240 you can use Python in object oriented programming, which 74 00:03:11,240 --> 00:03:12,770 is quite popular nowadays. 75 00:03:12,770 --> 00:03:15,500 And we'll also take a look at deploying websites to the internet. 76 00:03:15,500 --> 00:03:17,880 And in particular, we'll look at building web-based games 77 00:03:17,880 --> 00:03:19,880 and look at the idea of artificial intelligence, 78 00:03:19,880 --> 00:03:23,070 something that might come up if you took a class like CS182 here at Harvard, 79 00:03:23,070 --> 00:03:25,770 which is the artificial intelligence class, looking at ideas of, 80 00:03:25,770 --> 00:03:28,760 OK, how do you program a computer to behave intelligently. 81 00:03:28,760 --> 00:03:31,070 And in particular, in the context of a web-based game, 82 00:03:31,070 --> 00:03:33,326 how can you program a computerized AI to be 83 00:03:33,326 --> 00:03:36,200 able to figure out the best move to make in any particular situation. 84 00:03:36,200 --> 00:03:38,810 So we'll take a look at that later this afternoon as well. 85 00:03:38,810 --> 00:03:40,049 But all of that awaits. 86 00:03:40,049 --> 00:03:42,590 Questions about directions that we're going today or anything 87 00:03:42,590 --> 00:03:45,414 that I've covered so far? 88 00:03:45,414 --> 00:03:47,580 All right, with that, we'll go ahead and get started 89 00:03:47,580 --> 00:03:49,257 by just taking a brief look at Python. 90 00:03:49,257 --> 00:03:51,090 The beginning of this is going to be largely 91 00:03:51,090 --> 00:03:55,500 review for if you remember in programming in Python from way 92 00:03:55,500 --> 00:03:57,280 back in the days of CS50. 93 00:03:57,280 --> 00:04:00,000 And so the most basic Python application that we could write-- 94 00:04:00,000 --> 00:04:03,150 I'll create a new file, we'll call it hello.py-- 95 00:04:03,150 --> 00:04:05,400 just looks something like this. 96 00:04:05,400 --> 00:04:09,840 We would say "print" and then "hello world." 97 00:04:09,840 --> 00:04:11,100 Simple programming like this. 98 00:04:11,100 --> 00:04:14,099 But in the context of this, there are at least two important ideas here. 99 00:04:14,099 --> 00:04:16,230 Print, in this case, is a function. 100 00:04:16,230 --> 00:04:19,410 And functions you can just think of as these abstractions, 101 00:04:19,410 --> 00:04:22,290 these pieces of code that perform some sort of behavior. 102 00:04:22,290 --> 00:04:24,540 And I say abstraction in the sense that I don't really 103 00:04:24,540 --> 00:04:27,297 care how Python has actually implemented the Print function. 104 00:04:27,297 --> 00:04:30,255 I just need to know that the Print function exists and I can provide it 105 00:04:30,255 --> 00:04:33,030 a string, some sequence of characters like "hello world," 106 00:04:33,030 --> 00:04:35,060 and when I run this program-- 107 00:04:35,060 --> 00:04:39,870 and I can run the program by running a command just like Python, hello.py-- 108 00:04:39,870 --> 00:04:42,509 when I run that program, I end up getting "hello world" 109 00:04:42,509 --> 00:04:43,800 printed to the terminal screen. 110 00:04:43,800 --> 00:04:45,150 So fairly straightforward. 111 00:04:45,150 --> 00:04:47,970 And that was the most basic Python application that we could write. 112 00:04:47,970 --> 00:04:49,740 But, of course, like all programming languages, 113 00:04:49,740 --> 00:04:51,760 Python has many more features than just that. 114 00:04:51,760 --> 00:04:54,630 And one key idea that we wanted to explore 115 00:04:54,630 --> 00:04:56,580 was the idea of variables in Python. 116 00:04:56,580 --> 00:05:00,840 And variables in Python, if you recall, from CS50, differed from variables in C 117 00:05:00,840 --> 00:05:02,181 in what way? 118 00:05:02,181 --> 00:05:05,430 There are number of ways, but what's one important way in which variables in C 119 00:05:05,430 --> 00:05:06,710 and variables in Python were different? 120 00:05:06,710 --> 00:05:07,297 Yeah. 121 00:05:07,297 --> 00:05:10,272 AUDIENCE: [INAUDIBLE] 122 00:05:10,272 --> 00:05:11,980 BRIAN YU: Yeah, you don't need to declare 123 00:05:11,980 --> 00:05:13,870 the types of variables in Python. 124 00:05:13,870 --> 00:05:16,090 And Python has a number of different variable types. 125 00:05:16,090 --> 00:05:17,890 So I have integer types. 126 00:05:17,890 --> 00:05:21,200 So I could say a equals 28, for instance. 127 00:05:21,200 --> 00:05:23,320 There are floating point types, just like C has. 128 00:05:23,320 --> 00:05:25,470 I could say b equals 2.8, for instance. 129 00:05:25,470 --> 00:05:27,944 And that's a floating point number, a decimal number. 130 00:05:27,944 --> 00:05:29,110 But it also has other types. 131 00:05:29,110 --> 00:05:31,930 It has Boolean values, like true and false. 132 00:05:31,930 --> 00:05:34,060 So we would say c equals true. 133 00:05:34,060 --> 00:05:38,187 Capital T for true, capital F for false, is just the way that Python 134 00:05:38,187 --> 00:05:39,520 happens to do Boolean variables. 135 00:05:39,520 --> 00:05:42,694 It has a capital T for true, capital F for false. 136 00:05:42,694 --> 00:05:44,860 There are a number of different types for variables. 137 00:05:44,860 --> 00:05:47,620 Python even has what's called a NoneType, which is a type used 138 00:05:47,620 --> 00:05:49,660 to represent the absence of a value. 139 00:05:49,660 --> 00:05:52,110 So I could set a variable equal to None. 140 00:05:52,110 --> 00:05:56,860 And None just happens to be a value of its own special type called NoneType, 141 00:05:56,860 --> 00:06:00,667 that just represents the fact that there is no value in a particular place. 142 00:06:00,667 --> 00:06:03,250 So you might imagine situations, which we'll in fact see later 143 00:06:03,250 --> 00:06:06,670 on today, where it's valuable to have some sort of representation of the idea 144 00:06:06,670 --> 00:06:09,970 that you have no value stored in a particular location. 145 00:06:09,970 --> 00:06:12,040 Now, just because we don't have to declare 146 00:06:12,040 --> 00:06:14,020 the types of variables in Python, doesn't 147 00:06:14,020 --> 00:06:16,190 mean that those types don't exist. 148 00:06:16,190 --> 00:06:19,510 And if you try and perform operations on values 149 00:06:19,510 --> 00:06:22,450 that the types don't line up for, or don't quite match up for, 150 00:06:22,450 --> 00:06:25,420 you could, in fact, run into errors there as well. 151 00:06:25,420 --> 00:06:28,780 So, brief recap of variables, the idea variable types. 152 00:06:28,780 --> 00:06:32,770 The next thing that we saw when we were exploring Python in the case of CS50 153 00:06:32,770 --> 00:06:34,690 was looking at conditions. 154 00:06:34,690 --> 00:06:36,550 So we would see examples like, all right, 155 00:06:36,550 --> 00:06:41,050 if x is equal to a value like 10, I could have conditions and say, 156 00:06:41,050 --> 00:06:47,650 OK, if x is greater than 0, then print x as positive. 157 00:06:47,650 --> 00:06:52,720 Elif, was Python's shorthand for else if, if x is less than 0, then 158 00:06:52,720 --> 00:06:54,460 I'll print x is negative. 159 00:06:54,460 --> 00:06:56,902 And then else, I'll print, OK, x is 0. 160 00:06:56,902 --> 00:06:59,110 If it's not positive and negative, it has to be zero. 161 00:06:59,110 --> 00:07:01,235 So important things to notice here are the keywords 162 00:07:01,235 --> 00:07:04,914 if, elif, and else are the conditions for if something is true, otherwise, 163 00:07:04,914 --> 00:07:07,330 if something else is true, else if something else is true. 164 00:07:07,330 --> 00:07:11,290 And importantly all the code inside of the if blocks are indented. 165 00:07:11,290 --> 00:07:13,180 And this indentation is important in Python. 166 00:07:13,180 --> 00:07:14,930 Unlike other languages, like [INAUDIBLE],, 167 00:07:14,930 --> 00:07:18,280 where indentation and white space is optional, in Python it is mandatory. 168 00:07:18,280 --> 00:07:21,400 The indentation is how you tell the program which pieces of code 169 00:07:21,400 --> 00:07:23,810 are located inside of which blocks. 170 00:07:23,810 --> 00:07:27,100 And so I could run this program, run Python, hello dot pi, in this case. 171 00:07:27,100 --> 00:07:29,400 And it says x is positive, which it is. 172 00:07:29,400 --> 00:07:33,280 And now of course, this program is going to behave exactly the same way 173 00:07:33,280 --> 00:07:37,942 no matter what it is that I have typed into the program-- 174 00:07:37,942 --> 00:07:40,400 because I'm not prompted to type anything into the program. 175 00:07:40,400 --> 00:07:42,700 So I could make this program responsive to input. 176 00:07:42,700 --> 00:07:45,750 I might want to prompt the user for OK, please type in a number. 177 00:07:45,750 --> 00:07:47,551 And when you type in a number, then we're 178 00:07:47,551 --> 00:07:49,800 going to tell you if it's positive, negative, or zero. 179 00:07:49,800 --> 00:07:51,850 And in CS50 how did we do this? 180 00:07:51,850 --> 00:07:57,640 What was the function we used in order to get input in integer from the user? 181 00:07:57,640 --> 00:08:00,600 Anyone remember name of that function? 182 00:08:00,600 --> 00:08:03,130 183 00:08:03,130 --> 00:08:05,230 Name of the function that gets an integer? 184 00:08:05,230 --> 00:08:07,630 AUDIENCE: [INAUDIBLE] 185 00:08:07,630 --> 00:08:10,320 BRIAN YU: Someone said it. 186 00:08:10,320 --> 00:08:10,850 Get int? 187 00:08:10,850 --> 00:08:12,308 OK, I think I heard someone say it. 188 00:08:12,308 --> 00:08:15,270 Get int was the function that we used in the CS50 library in Python 189 00:08:15,270 --> 00:08:17,040 in order to get an integer from the user. 190 00:08:17,040 --> 00:08:20,460 Of course, that function is only in the CS50 library. 191 00:08:20,460 --> 00:08:22,320 You can install the CS50 library. 192 00:08:22,320 --> 00:08:25,530 It's pre-installed in CS50 IDE, but you can install it elsewhere in order 193 00:08:25,530 --> 00:08:27,600 to get access to that get in function. 194 00:08:27,600 --> 00:08:30,030 But in practice, most computer installations 195 00:08:30,030 --> 00:08:32,440 don't have the CS50 library installed by default. 196 00:08:32,440 --> 00:08:35,159 And so how would you get input from the user if you wanted to? 197 00:08:35,159 --> 00:08:38,130 Well, Python 3, the latest version of Python at least, 198 00:08:38,130 --> 00:08:40,679 comes with a function called input. 199 00:08:40,679 --> 00:08:43,657 And the input function basically just gets input 200 00:08:43,657 --> 00:08:45,990 from the user, not something we really explored in CS50, 201 00:08:45,990 --> 00:08:47,040 but something you can do. 202 00:08:47,040 --> 00:08:49,609 So I could say something like, OK, type a number. 203 00:08:49,609 --> 00:08:51,900 I'm asking the user to type in a number, prompting them 204 00:08:51,900 --> 00:08:54,420 for some sort of input setting, that value equal to x. 205 00:08:54,420 --> 00:08:58,310 And then checking to see if x is positive, negative, or zero. 206 00:08:58,310 --> 00:09:00,780 And so I could run this, run Python, hello dot pi. 207 00:09:00,780 --> 00:09:01,610 Type in a number. 208 00:09:01,610 --> 00:09:03,640 I'll type in 0 for example. 209 00:09:03,640 --> 00:09:05,760 And OK, I get an error. 210 00:09:05,760 --> 00:09:09,240 This is the first example of a Python exception that we've seen. 211 00:09:09,240 --> 00:09:12,450 And the type of this error, what kind of exception has been raised-- 212 00:09:12,450 --> 00:09:14,040 is the terminology we'll use-- 213 00:09:14,040 --> 00:09:15,370 is a type error. 214 00:09:15,370 --> 00:09:19,350 And here's the type error, greater than symbol not supported between instances 215 00:09:19,350 --> 00:09:22,860 of str, short for string, and it. 216 00:09:22,860 --> 00:09:24,810 And so this is an exception that highlights 217 00:09:24,810 --> 00:09:28,530 what I was mentioning just a moment ago, that even though we didn't give types 218 00:09:28,530 --> 00:09:32,670 to variables explicitly, those variables still have types. 219 00:09:32,670 --> 00:09:37,260 Namely, what I'm comparing x greater than 0, 0 is an int. 220 00:09:37,260 --> 00:09:38,670 And x, it claims-- 221 00:09:38,670 --> 00:09:42,847 Python's interpreter is saying-- is a str, a string. 222 00:09:42,847 --> 00:09:46,180 And that's ultimately because this input function asking me to type in something 223 00:09:46,180 --> 00:09:50,454 at the command prompt is asking for just any input, which 224 00:09:50,454 --> 00:09:53,120 could have been a number, but it also could have been some text. 225 00:09:53,120 --> 00:09:55,930 I could have typed hello or hi at the command prompt. 226 00:09:55,930 --> 00:09:59,220 And it would've been valid input. 227 00:09:59,220 --> 00:10:02,350 And so what I need to do in order to make this work is something 228 00:10:02,350 --> 00:10:06,040 called typecasting, the idea of converting something from one type 229 00:10:06,040 --> 00:10:09,550 into another type in order to make it work. x right now is a string. 230 00:10:09,550 --> 00:10:12,204 And I want to convert it into an integer in order 231 00:10:12,204 --> 00:10:13,870 to allow myself to do these comparisons. 232 00:10:13,870 --> 00:10:16,600 Is x greater than zero or less than zero or so forth? 233 00:10:16,600 --> 00:10:19,030 And the easiest way to do that is just use 234 00:10:19,030 --> 00:10:21,910 a function called int in Python that take something and convert it 235 00:10:21,910 --> 00:10:23,210 into an integer. 236 00:10:23,210 --> 00:10:29,820 So I'll wrap this input function inside of an int function. 237 00:10:29,820 --> 00:10:34,140 And so here is the idea that I'm taking the output of the input function 238 00:10:34,140 --> 00:10:37,547 and passing it as input to the int function. 239 00:10:37,547 --> 00:10:40,380 And so it's often useful to think about functions in the way of what 240 00:10:40,380 --> 00:10:41,820 are the inputs to this function? 241 00:10:41,820 --> 00:10:43,309 What is the output of the function? 242 00:10:43,309 --> 00:10:45,725 And thinking about trying to relate those things together. 243 00:10:45,725 --> 00:10:48,420 As you start to build more complex, more sophisticated programs, 244 00:10:48,420 --> 00:10:50,160 you'll begin to use more and more functions. 245 00:10:50,160 --> 00:10:52,710 And being able to reason about OK, what is the input to the function? 246 00:10:52,710 --> 00:10:54,168 What is the output to the function? 247 00:10:54,168 --> 00:10:56,540 Is ultimately going to be quite helpful. 248 00:10:56,540 --> 00:10:58,310 So now I type Python hello dot pi. 249 00:10:58,310 --> 00:10:59,910 I type a number like zero. 250 00:10:59,910 --> 00:11:00,630 x is zero. 251 00:11:00,630 --> 00:11:02,819 It was able to convert my input into an integer, 252 00:11:02,819 --> 00:11:05,610 and then run some comparisons, as a greater than or less than zero, 253 00:11:05,610 --> 00:11:06,820 for instance. 254 00:11:06,820 --> 00:11:09,360 If I type in a positive number, 28, x is positive. 255 00:11:09,360 --> 00:11:10,110 OK, great. 256 00:11:10,110 --> 00:11:11,940 I type in a negative number, a negative 50. 257 00:11:11,940 --> 00:11:13,157 OK, x is negative. 258 00:11:13,157 --> 00:11:15,490 It will be able to perform these comparisons on the fly. 259 00:11:15,490 --> 00:11:17,365 Now, of course, if I type in something else-- 260 00:11:17,365 --> 00:11:20,197 I type in beyond, just some string for instance-- now 261 00:11:20,197 --> 00:11:22,530 I'm getting a different exception that's getting thrown. 262 00:11:22,530 --> 00:11:24,240 I'm getting a value error. 263 00:11:24,240 --> 00:11:28,030 Invalid literal for the int function with base 10 beyond. 264 00:11:28,030 --> 00:11:31,920 In other words, it can't take the word beyond, the string that I inputted, 265 00:11:31,920 --> 00:11:33,630 and convert it into an integer. 266 00:11:33,630 --> 00:11:34,905 And so what's Python going to do about it? 267 00:11:34,905 --> 00:11:36,321 It doesn't really know what to do. 268 00:11:36,321 --> 00:11:37,540 So it raises an exception. 269 00:11:37,540 --> 00:11:39,170 It causes an error. 270 00:11:39,170 --> 00:11:43,169 And that error is a value error. 271 00:11:43,169 --> 00:11:44,210 So we've seen a lot here. 272 00:11:44,210 --> 00:11:45,470 We've seen getting input. 273 00:11:45,470 --> 00:11:47,060 We've seen functions input and output. 274 00:11:47,060 --> 00:11:50,300 We've seen Python exceptions and how to handle those. 275 00:11:50,300 --> 00:11:51,650 Questions about anything so far? 276 00:11:51,650 --> 00:11:53,179 How do we feel about it? 277 00:11:53,179 --> 00:11:54,970 If you could just use the feedback for, let 278 00:11:54,970 --> 00:11:57,100 me know are things making sense generally? 279 00:11:57,100 --> 00:11:58,610 Is this familiar? 280 00:11:58,610 --> 00:11:59,110 All right. 281 00:11:59,110 --> 00:11:59,320 Great. 282 00:11:59,320 --> 00:12:01,694 Seems like most of this is review, most of this familiar. 283 00:12:01,694 --> 00:12:04,030 And we'll move on to other data types as well. 284 00:12:04,030 --> 00:12:07,060 Important in Python are the idea of sequence data 285 00:12:07,060 --> 00:12:10,690 types, the idea that data type don't need to just contain one value. 286 00:12:10,690 --> 00:12:12,670 They can contain sequences of values. 287 00:12:12,670 --> 00:12:15,410 So I could have a name for instance. 288 00:12:15,410 --> 00:12:20,520 I could say OK, name is going to be Josh, for instance. 289 00:12:20,520 --> 00:12:23,650 And Josh is us type str, a string, but it's also 290 00:12:23,650 --> 00:12:26,710 a sequence of characters, whereby if I wanted to print out 291 00:12:26,710 --> 00:12:28,750 the first character in Josh's name, I could say 292 00:12:28,750 --> 00:12:32,800 OK, print out name Square Bracket zero. 293 00:12:32,800 --> 00:12:35,980 And if I were to run this program, it would print out just the letter J, 294 00:12:35,980 --> 00:12:38,410 printing out the first item in this sequence. 295 00:12:38,410 --> 00:12:41,290 And a string is the simplest example of a sequence that we've seen. 296 00:12:41,290 --> 00:12:45,750 It's just a sequence of one character after another after another. 297 00:12:45,750 --> 00:12:48,810 In addition to sequences being strings of text, 298 00:12:48,810 --> 00:12:54,000 we also have lists are also examples of sequences in Python. 299 00:12:54,000 --> 00:12:55,960 So I might say OK, we have multiple names. 300 00:12:55,960 --> 00:12:58,740 And so we have Krishna and we have Athena 301 00:12:58,740 --> 00:13:02,264 and we have Julia as examples of a list of possible values. 302 00:13:02,264 --> 00:13:04,930 And if I wanted to get the first item in this list for instance, 303 00:13:04,930 --> 00:13:08,430 I could say OK, print names Square Bracket zero. 304 00:13:08,430 --> 00:13:11,790 Remember that list as with arrays and C are zero index. 305 00:13:11,790 --> 00:13:14,100 The first element is item number zero. 306 00:13:14,100 --> 00:13:18,420 And if I print that out, it prints out Krishna, the first name on the list. 307 00:13:18,420 --> 00:13:21,990 And I can say print names one to get the second item in the list. 308 00:13:21,990 --> 00:13:22,954 It gets Athena. 309 00:13:22,954 --> 00:13:25,120 I print names two to get the third item in the list. 310 00:13:25,120 --> 00:13:26,310 That's Julia. 311 00:13:26,310 --> 00:13:28,760 There are other tricks that you can do here as well. 312 00:13:28,760 --> 00:13:30,510 If you want to go backwards for instance-- 313 00:13:30,510 --> 00:13:32,176 I don't want the first item in the list. 314 00:13:32,176 --> 00:13:33,600 I want the last item in the list-- 315 00:13:33,600 --> 00:13:35,200 you can use negative numbers. 316 00:13:35,200 --> 00:13:38,440 So if I say print names negative one, for instance, that's going to say, 317 00:13:38,440 --> 00:13:40,950 OK, let's go backwards and get me the last item in the list. 318 00:13:40,950 --> 00:13:43,690 So if I print out names Square Bracket negative 1, 319 00:13:43,690 --> 00:13:46,580 that's going to print out which name? 320 00:13:46,580 --> 00:13:47,080 Julia. 321 00:13:47,080 --> 00:13:47,390 Great. 322 00:13:47,390 --> 00:13:49,040 So that's the last item in the list. 323 00:13:49,040 --> 00:13:53,400 Prints that out because that's Square Bracket negative 1. 324 00:13:53,400 --> 00:13:56,010 The other important sequence data type that will often see 325 00:13:56,010 --> 00:13:57,660 is called a tuple or a tuple. 326 00:13:57,660 --> 00:13:59,440 You'll hear it pronounced both ways. 327 00:13:59,440 --> 00:14:03,070 And that's useful for immutable sequences, 328 00:14:03,070 --> 00:14:05,250 sequences that cannot change. 329 00:14:05,250 --> 00:14:08,100 And so you might imagine for if you have a fixed number of things 330 00:14:08,100 --> 00:14:11,310 like a coordinate pair, like an x-coordinate and a y-coordinate, 331 00:14:11,310 --> 00:14:13,800 a tuple or a tuple might make sense for here. 332 00:14:13,800 --> 00:14:18,570 I say coordinates equals like, 2, 8 x-coordinate y-coordinate. 333 00:14:18,570 --> 00:14:20,730 And now I have a first item and a second item. 334 00:14:20,730 --> 00:14:22,470 I can index into them with square bracket 335 00:14:22,470 --> 00:14:26,760 0 square bracket 1 to get it the first and second items respectively. 336 00:14:26,760 --> 00:14:28,677 And I can use that syntax as well. 337 00:14:28,677 --> 00:14:30,510 This is also particularly useful if you ever 338 00:14:30,510 --> 00:14:33,390 need a function to return two values. 339 00:14:33,390 --> 00:14:35,940 Normally, a function can only return one thing. 340 00:14:35,940 --> 00:14:39,270 But if that one thing is a tuple, you can take that topple and split it up 341 00:14:39,270 --> 00:14:40,620 into all its component parts. 342 00:14:40,620 --> 00:14:43,500 So you have the ability to effectively have multiple things 343 00:14:43,500 --> 00:14:48,790 that you're returning from a function by taking advantage of this functionality. 344 00:14:48,790 --> 00:14:50,310 Questions about anything so far? 345 00:14:50,310 --> 00:14:50,809 Yeah? 346 00:14:50,809 --> 00:14:54,000 AUDIENCE: [INAUDIBLE] 347 00:14:54,000 --> 00:14:57,920 348 00:14:57,920 --> 00:14:58,990 BRIAN YU: Good question. 349 00:14:58,990 --> 00:15:04,267 So the question is why would you use a tuple instead of a list of size two? 350 00:15:04,267 --> 00:15:07,100 So first of all, tuples don't necessarily need to be just two items. 351 00:15:07,100 --> 00:15:09,880 They could potentially be more items than that. 352 00:15:09,880 --> 00:15:12,219 And so you could extend-- 353 00:15:12,219 --> 00:15:14,260 if I wanted a three dimensional coordinate plane, 354 00:15:14,260 --> 00:15:16,272 this could be two, eight, five, for instance. 355 00:15:16,272 --> 00:15:18,230 And you could have multiple things in sequence. 356 00:15:18,230 --> 00:15:19,521 It doesn't need to be just two. 357 00:15:19,521 --> 00:15:22,270 It could be any fixed number of them. 358 00:15:22,270 --> 00:15:27,139 But there are certain advantages, in particular, the tuple is immutable, 359 00:15:27,139 --> 00:15:28,180 meaning it cannot change. 360 00:15:28,180 --> 00:15:30,250 And so that can help to defend against certain kinds of errors 361 00:15:30,250 --> 00:15:33,070 if you don't want to allow a data structure to be able to change. 362 00:15:33,070 --> 00:15:34,630 And there are certain operations you can perform 363 00:15:34,630 --> 00:15:35,860 on them that are more efficient. 364 00:15:35,860 --> 00:15:37,859 So a lot of things are just trying to figure out 365 00:15:37,859 --> 00:15:41,419 which is the right choice of data structure to fit the type of thing 366 00:15:41,419 --> 00:15:42,460 that you're trying to do. 367 00:15:42,460 --> 00:15:45,418 And we'll take a look at other data structures in just a moment as well 368 00:15:45,418 --> 00:15:49,340 and compare their advantages and disadvantages. 369 00:15:49,340 --> 00:15:49,900 Yeah? 370 00:15:49,900 --> 00:15:52,381 AUDIENCE: [INAUDIBLE] 371 00:15:52,381 --> 00:15:53,380 BRIAN YU: Good question. 372 00:15:53,380 --> 00:15:56,338 Question is do all the elements in a tuple need to be of the same type? 373 00:15:56,338 --> 00:15:57,400 No, they do not. 374 00:15:57,400 --> 00:16:00,820 I could have two, eight, and hello, and that would 375 00:16:00,820 --> 00:16:02,317 be a totally valid tuple in Python. 376 00:16:02,317 --> 00:16:03,400 They could be of any type. 377 00:16:03,400 --> 00:16:04,317 Same is true of lists. 378 00:16:04,317 --> 00:16:05,691 You can have them be of any type. 379 00:16:05,691 --> 00:16:07,530 They don't necessarily need to be the same. 380 00:16:07,530 --> 00:16:10,840 However, oftentimes, in the case of lists for consistency, 381 00:16:10,840 --> 00:16:12,700 you will want them to be of the same type, 382 00:16:12,700 --> 00:16:14,826 because the general idea of the semantics of a list 383 00:16:14,826 --> 00:16:16,658 is you should hopefully be able to treat all 384 00:16:16,658 --> 00:16:18,250 the elements in the list the same way. 385 00:16:18,250 --> 00:16:21,100 Usually, it's a list of things that the same type of thing, 386 00:16:21,100 --> 00:16:24,634 whereby you'll have a list of names or a list of student objects. 387 00:16:24,634 --> 00:16:26,800 And we'll look at object oriented programming later. 388 00:16:26,800 --> 00:16:27,980 And that's actually another case where it 389 00:16:27,980 --> 00:16:30,640 might be useful to differentiate between a list and a tuple, 390 00:16:30,640 --> 00:16:32,110 that frequently you use a list when you've 391 00:16:32,110 --> 00:16:34,694 got a whole bunch of things that are of the same type of thing 392 00:16:34,694 --> 00:16:36,360 and you want to treat them the same way. 393 00:16:36,360 --> 00:16:38,200 And a tuple is often more useful if you have 394 00:16:38,200 --> 00:16:40,900 a bunch of different types of things, but you still 395 00:16:40,900 --> 00:16:45,550 want to encapsulate together in a single representation. 396 00:16:45,550 --> 00:16:46,509 Good questions. 397 00:16:46,509 --> 00:16:47,050 Other things? 398 00:16:47,050 --> 00:16:53,904 399 00:16:53,904 --> 00:16:56,070 We'll talk about loops and functions, and then we'll 400 00:16:56,070 --> 00:16:58,600 dive into a couple more advanced features. 401 00:16:58,600 --> 00:17:01,910 So in order to loop over a sequence of things-- 402 00:17:01,910 --> 00:17:03,080 so I have a list of names. 403 00:17:03,080 --> 00:17:06,270 I have Krishna Athena, Julia, and I'll add Josh there too. 404 00:17:06,270 --> 00:17:09,300 If I want to loop over all of them, the easiest way to do that in Python 405 00:17:09,300 --> 00:17:12,569 is to say for name in names. 406 00:17:12,569 --> 00:17:16,119 What I'm doing here is I'm saying I want to loop over this array of names 407 00:17:16,119 --> 00:17:19,230 and give each one the name name. 408 00:17:19,230 --> 00:17:23,970 And I'll just print out that name. 409 00:17:23,970 --> 00:17:27,990 I'm looping over my list of names, calling each item in the list name 410 00:17:27,990 --> 00:17:29,790 and printing that out. 411 00:17:29,790 --> 00:17:35,490 So if I run this program, I get all the names printed out one line at a time. 412 00:17:35,490 --> 00:17:38,330 If I wanted to print something out a little fancier, 413 00:17:38,330 --> 00:17:40,670 I could say like, hello-- 414 00:17:40,670 --> 00:17:43,141 if I want to say hello to the person's name, 415 00:17:43,141 --> 00:17:45,890 I can use what's called a Python format string, which you probably 416 00:17:45,890 --> 00:17:49,550 remember from CS50 whereby I and use these curly braces to say hello. 417 00:17:49,550 --> 00:17:53,210 And then in Curly Braces name, I have to put an F in front of the string 418 00:17:53,210 --> 00:17:54,950 to say this is a formatted string. 419 00:17:54,950 --> 00:17:57,140 But the curly braces are basically signifying 420 00:17:57,140 --> 00:17:59,840 I would like to plug in some value here, in particular, I 421 00:17:59,840 --> 00:18:03,620 want to plug in whatever the name is, whatever the value of the variable name 422 00:18:03,620 --> 00:18:04,310 happens to be. 423 00:18:04,310 --> 00:18:05,480 And I'm printing that out. 424 00:18:05,480 --> 00:18:07,670 So printing hello common name. 425 00:18:07,670 --> 00:18:08,900 I print that out. 426 00:18:08,900 --> 00:18:12,230 We get hello, comma, and then each of the names, a formatted string. 427 00:18:12,230 --> 00:18:17,110 And certainly, we'll see more formatted strings later on too. 428 00:18:17,110 --> 00:18:21,130 So you can use for name in names to iterate this sort of idea 429 00:18:21,130 --> 00:18:23,260 to iterate over any kind of sequence. 430 00:18:23,260 --> 00:18:26,110 If instead of name, we just had a single name. 431 00:18:26,110 --> 00:18:28,240 And OK, a name equals Julia. 432 00:18:28,240 --> 00:18:32,920 I could say for character in name, let me go ahead 433 00:18:32,920 --> 00:18:35,920 and print out the character. 434 00:18:35,920 --> 00:18:38,164 Name as a sequence, it's a sequence of characters. 435 00:18:38,164 --> 00:18:41,080 And if I print out each character one at a time, what I'm going to get 436 00:18:41,080 --> 00:18:44,269 is just one character, one on each line, one at a time. 437 00:18:44,269 --> 00:18:46,060 So that works for those types of sequences. 438 00:18:46,060 --> 00:18:47,310 It'll work for tuples as well. 439 00:18:47,310 --> 00:18:52,660 You can do this kind of iteration over any type of sequence. 440 00:18:52,660 --> 00:18:55,300 You can also iterate over just a range of numbers. 441 00:18:55,300 --> 00:18:57,680 A range is a particular type of sequence. 442 00:18:57,680 --> 00:19:05,320 So I could say for I in range 10, print I. Range 10 is just a sequence. 443 00:19:05,320 --> 00:19:09,370 It's going to generate numbers between 0 up through, but not including 10. 444 00:19:09,370 --> 00:19:11,910 So 0 up through 9, for instance. 445 00:19:11,910 --> 00:19:16,390 So if I say for I in range 10, print I. That'll give me 0 all the way 446 00:19:16,390 --> 00:19:17,860 through 9. 447 00:19:17,860 --> 00:19:20,740 I can also change the starting point of a range if need be. 448 00:19:20,740 --> 00:19:25,180 So if I say for I in range 5, 10, that's going to start at 5. 449 00:19:25,180 --> 00:19:28,090 Go all the way up through 10, but not including 10. 450 00:19:28,090 --> 00:19:28,912 So I do that. 451 00:19:28,912 --> 00:19:31,870 And actually, I'll just put both side by side so you can see them both. 452 00:19:31,870 --> 00:19:34,400 I get 5, 6, 7, 8, 9. 453 00:19:34,400 --> 00:19:37,030 So it goes from 5 up through, but not including 10. 454 00:19:37,030 --> 00:19:39,580 And range can even take a third argument if I want to, 455 00:19:39,580 --> 00:19:41,950 which is the step amount, in other words, how 456 00:19:41,950 --> 00:19:44,050 much to increment by after each step. 457 00:19:44,050 --> 00:19:49,810 So I could say I in range 0 through 100 stepping by fives. 458 00:19:49,810 --> 00:19:53,200 So that's going to take me from 0 all the way up to, but not including 100, 459 00:19:53,200 --> 00:19:55,000 going five at a time. 460 00:19:55,000 --> 00:19:59,870 And if I run that, I get 0, 5, 10, 15, 20, all the way up through 95, 461 00:19:59,870 --> 00:20:01,867 because after the next five it would hit 100. 462 00:20:01,867 --> 00:20:03,700 So a bunch of different ways to iterate over 463 00:20:03,700 --> 00:20:07,900 sequences of values, whether they're ranges or strings or lists, 464 00:20:07,900 --> 00:20:11,002 or other types of sequences. 465 00:20:11,002 --> 00:20:12,460 Questions about any of that so far? 466 00:20:12,460 --> 00:20:12,960 Yeah? 467 00:20:12,960 --> 00:20:16,352 AUDIENCE: [INAUDIBLE] 468 00:20:16,352 --> 00:20:17,759 469 00:20:17,759 --> 00:20:18,952 BRIAN YU: Oh, good question. 470 00:20:18,952 --> 00:20:21,160 So the question is what if I wondered all the numbers 471 00:20:21,160 --> 00:20:25,150 to show up on one line instead of each one on a separate line? 472 00:20:25,150 --> 00:20:29,860 So Python's print function by default will always add a new line 473 00:20:29,860 --> 00:20:31,720 after the end of the statement. 474 00:20:31,720 --> 00:20:33,040 But you can change that. 475 00:20:33,040 --> 00:20:35,170 And so we'll talk about functions in just a moment. 476 00:20:35,170 --> 00:20:40,310 But Python allows for functions to have sort of optional arguments. 477 00:20:40,310 --> 00:20:42,730 And in this case, print has an option argument 478 00:20:42,730 --> 00:20:47,170 called end, which is what should be at the end of the line? 479 00:20:47,170 --> 00:20:50,680 And the end value by default is the new line character, backslash n, 480 00:20:50,680 --> 00:20:52,240 which you might remember from CS50. 481 00:20:52,240 --> 00:20:53,239 But I could change that. 482 00:20:53,239 --> 00:20:58,360 I could make end be instead just the space character, just one new space. 483 00:20:58,360 --> 00:21:03,880 And I'll go from up to 30 maybe, so as not to take up too much space. 484 00:21:03,880 --> 00:21:09,220 But for if I run this program now, now I get 0, 5, 10, 15, 20, 25, all 485 00:21:09,220 --> 00:21:10,892 in the same line separated by spaces. 486 00:21:10,892 --> 00:21:13,600 And you'll notice in my terminal prompt is even on the same line, 487 00:21:13,600 --> 00:21:16,810 because nowhere in my program did I say OK, go on to a new line now. 488 00:21:16,810 --> 00:21:21,770 It's always printing out a space at the end of each one. 489 00:21:21,770 --> 00:21:23,190 Good question. 490 00:21:23,190 --> 00:21:25,530 Other things? 491 00:21:25,530 --> 00:21:27,750 How about I take any like, how do I do this in Python 492 00:21:27,750 --> 00:21:29,750 if there are things that you're wondering about? 493 00:21:29,750 --> 00:21:32,760 494 00:21:32,760 --> 00:21:33,260 All right. 495 00:21:33,260 --> 00:21:37,650 We'll take a look at functions and some data structures as well. 496 00:21:37,650 --> 00:21:39,440 Actually, I'll do data structures first. 497 00:21:39,440 --> 00:21:43,094 So oftentimes in Python you're going to want to store data in some way. 498 00:21:43,094 --> 00:21:45,260 And there are a number of different data structures. 499 00:21:45,260 --> 00:21:48,426 And it's important to have a grasp of what the different data structures are 500 00:21:48,426 --> 00:21:49,710 and what makes them different. 501 00:21:49,710 --> 00:21:54,380 And so one of the simplest data structures is a set. 502 00:21:54,380 --> 00:21:57,560 So we have a list, which is an ordered sequence of elements. 503 00:21:57,560 --> 00:22:01,289 A set is an unordered collection of elements. 504 00:22:01,289 --> 00:22:03,080 And that collection doesn't have any order, 505 00:22:03,080 --> 00:22:05,180 and also all of the elements of the set are unique, 506 00:22:05,180 --> 00:22:07,596 much like a set in mathematics if you're familiar with it, 507 00:22:07,596 --> 00:22:10,296 a bunch of unique values that are not in any particular order. 508 00:22:10,296 --> 00:22:11,420 I can have a set of things. 509 00:22:11,420 --> 00:22:12,710 S is a set. 510 00:22:12,710 --> 00:22:17,120 And I can say something like, OK, let's add the number one to the set. 511 00:22:17,120 --> 00:22:19,070 And let's add the number 28 to the set. 512 00:22:19,070 --> 00:22:21,380 And let's add the number 50 to the set. 513 00:22:21,380 --> 00:22:25,800 And now let me print out the contents of this set. 514 00:22:25,800 --> 00:22:27,270 So I'll run this program. 515 00:22:27,270 --> 00:22:30,330 And it's giving me this set of things 1, 50, and 28. 516 00:22:30,330 --> 00:22:33,870 Notice this is not the same order as the order that I put these values in. 517 00:22:33,870 --> 00:22:35,730 The set doesn't maintain any sense of order. 518 00:22:35,730 --> 00:22:39,752 It just knows OK, it's got the number 1 and 50 and 28 in it somewhere. 519 00:22:39,752 --> 00:22:42,210 And that's useful to me if I want that collection of things 520 00:22:42,210 --> 00:22:43,530 to be inside the set. 521 00:22:43,530 --> 00:22:48,870 And so now I can ask questions like, print out if 28 is in the set. 522 00:22:48,870 --> 00:22:51,510 Is the number 28 in the set? 523 00:22:51,510 --> 00:22:55,860 Or not is 28 in the set. 524 00:22:55,860 --> 00:22:56,650 And I'll try that. 525 00:22:56,650 --> 00:22:57,400 OK, true. 526 00:22:57,400 --> 00:23:00,040 Yes, 28 is in the set. 527 00:23:00,040 --> 00:23:02,680 Is the number 29 in the set? 528 00:23:02,680 --> 00:23:04,012 Try that. 529 00:23:04,012 --> 00:23:04,720 Run that program. 530 00:23:04,720 --> 00:23:05,530 False. 531 00:23:05,530 --> 00:23:07,150 29 is not in the set. 532 00:23:07,150 --> 00:23:10,630 And sets are useful, because looking up whether something is in a set 533 00:23:10,630 --> 00:23:14,620 is more efficient than looking up whether something is in a list. 534 00:23:14,620 --> 00:23:16,360 Looking up whether something is in a list 535 00:23:16,360 --> 00:23:18,825 happens in what we used to call linear time. 536 00:23:18,825 --> 00:23:21,200 Basically, if you want to check if a value within a list, 537 00:23:21,200 --> 00:23:22,840 you're going to have to look through that entire list from start 538 00:23:22,840 --> 00:23:25,560 to potentially to the end, looking at one element at a time, checking. 539 00:23:25,560 --> 00:23:26,650 Is this element in the list? 540 00:23:26,650 --> 00:23:29,050 Is it in the list going all the way from start to finish? 541 00:23:29,050 --> 00:23:32,020 In the case of a set, the values are stored slightly differently. 542 00:23:32,020 --> 00:23:34,420 They're stored in something akin to what a hash table is. 543 00:23:34,420 --> 00:23:36,400 If you remember hash tables from CS50. 544 00:23:36,400 --> 00:23:39,490 So it's much more efficient to look up is this number inside of the set? 545 00:23:39,490 --> 00:23:41,680 Much in the same way that in CS50 speller problem 546 00:23:41,680 --> 00:23:44,410 set you were able to use a hash table potentially, to say 547 00:23:44,410 --> 00:23:46,100 is this word in the dictionary. 548 00:23:46,100 --> 00:23:49,660 And you were able to do that efficiently by the use of a hash table. 549 00:23:49,660 --> 00:23:51,782 So looking up whether something is in a set, 550 00:23:51,782 --> 00:23:54,490 ultimately more efficient than doing that same look up in a list, 551 00:23:54,490 --> 00:23:55,660 for example. 552 00:23:55,660 --> 00:23:58,890 So that can be cases where a set is oftentimes more helpful. 553 00:23:58,890 --> 00:24:02,320 Now a set just stores a whole bunch of values. 554 00:24:02,320 --> 00:24:05,950 Oftentimes, in Python or in JavaScript or in other languages 555 00:24:05,950 --> 00:24:08,500 you'll use you'll want to store not just values, 556 00:24:08,500 --> 00:24:12,084 but you want associate keys and values together. 557 00:24:12,084 --> 00:24:14,250 In other words, you want to store some sort of label 558 00:24:14,250 --> 00:24:16,660 or some sort of identifier, and some sort of value 559 00:24:16,660 --> 00:24:19,450 for each one of those identifiers, for instance. 560 00:24:19,450 --> 00:24:22,220 And so this is the idea of a Python dictionary, 561 00:24:22,220 --> 00:24:24,220 or what you might equivalently call a JavaScript 562 00:24:24,220 --> 00:24:26,080 object, which we'll look at tomorrow. 563 00:24:26,080 --> 00:24:28,810 But a Python dictionary is a very important data structure 564 00:24:28,810 --> 00:24:32,980 that will come up very, very frequently that associates keys and values 565 00:24:32,980 --> 00:24:35,590 that associate some sort of name with some sort of value 566 00:24:35,590 --> 00:24:37,420 associated with that name. 567 00:24:37,420 --> 00:24:42,370 And so let's say I wanted to store the ages of different people. 568 00:24:42,370 --> 00:24:45,880 And so I might say ages is going to be a Python dictionary. 569 00:24:45,880 --> 00:24:47,140 And we have a name Alice. 570 00:24:47,140 --> 00:24:49,480 And Alice is 22. 571 00:24:49,480 --> 00:24:51,010 And we have a name Bob. 572 00:24:51,010 --> 00:24:53,460 And Bob is 27. 573 00:24:53,460 --> 00:24:57,610 And so here we've created a Python dictionary called ages. 574 00:24:57,610 --> 00:25:00,986 And in this dictionary the keys are Alice and Bob. 575 00:25:00,986 --> 00:25:03,610 They're the things that we're going to use to look something up 576 00:25:03,610 --> 00:25:04,870 in this dictionary. 577 00:25:04,870 --> 00:25:07,630 And the value is what we're going to get when we do that look up. 578 00:25:07,630 --> 00:25:09,280 Like, how old is Alice? 579 00:25:09,280 --> 00:25:11,680 If I wanted to ask that question, I would print out 580 00:25:11,680 --> 00:25:15,160 OK, let's take the ages dictionary, and let me look up 581 00:25:15,160 --> 00:25:16,870 Alice inside of that dictionary. 582 00:25:16,870 --> 00:25:19,600 I would like to see how old Alice is by looking up 583 00:25:19,600 --> 00:25:25,370 what value is associated with the Alice key inside of this dictionary. 584 00:25:25,370 --> 00:25:26,420 So I run the program. 585 00:25:26,420 --> 00:25:28,220 And OK, I get print out 22. 586 00:25:28,220 --> 00:25:30,980 That is the value associated with the key Alice. 587 00:25:30,980 --> 00:25:35,240 And if I were to look up Bob, run the program again. 588 00:25:35,240 --> 00:25:35,960 OK, 27. 589 00:25:35,960 --> 00:25:39,290 That's the value associated with the Bob key. 590 00:25:39,290 --> 00:25:43,025 If I were to look up Charlie, at another name I get an error. 591 00:25:43,025 --> 00:25:44,900 In this case, I got a different type of error 592 00:25:44,900 --> 00:25:49,250 that we haven't seen before, a key error, meaning the key Charlie 593 00:25:49,250 --> 00:25:50,630 isn't present in the dictionary. 594 00:25:50,630 --> 00:25:53,330 I tried to look up a key that did not exist. 595 00:25:53,330 --> 00:25:56,810 And so I ran into an error there. 596 00:25:56,810 --> 00:25:59,550 I could add Charlie to the dictionary either by updating it here 597 00:25:59,550 --> 00:26:02,091 or I can also update a dictionary after I've already created. 598 00:26:02,091 --> 00:26:04,400 I could say OK, age is Charlie. 599 00:26:04,400 --> 00:26:06,730 Charlie is going to be 28, for instance. 600 00:26:06,730 --> 00:26:08,450 And so I print age is Charlie. 601 00:26:08,450 --> 00:26:09,920 And now OK, no more key error. 602 00:26:09,920 --> 00:26:11,870 Charlie is in the dictionary. 603 00:26:11,870 --> 00:26:14,850 And Charlie is 28 years old. 604 00:26:14,850 --> 00:26:19,740 So Python dictionaries can be used for that as well. 605 00:26:19,740 --> 00:26:24,220 Questions about sets, dictionaries, data structures, more generally? 606 00:26:24,220 --> 00:26:24,870 Yeah? 607 00:26:24,870 --> 00:26:28,435 AUDIENCE: Would you remove or edit existing keys in the dictionary? 608 00:26:28,435 --> 00:26:29,480 BRIAN YU: Great question. 609 00:26:29,480 --> 00:26:31,940 Can you remove or edit existing keys in the dictionary? 610 00:26:31,940 --> 00:26:32,480 Absolutely. 611 00:26:32,480 --> 00:26:34,550 So to edit a key for instance, if I want to say 612 00:26:34,550 --> 00:26:38,330 it's Alice's birthday, so Alice's birthday, the hash tag 613 00:26:38,330 --> 00:26:39,740 just get a comment. 614 00:26:39,740 --> 00:26:42,140 We're going to the age is Alice plus equals 615 00:26:42,140 --> 00:26:46,550 one, meaning take whatever Alice's age is, add one to it. 616 00:26:46,550 --> 00:26:49,150 You could also just set it equal to some other value entirely. 617 00:26:49,150 --> 00:26:54,700 But now if I were to print out Alice's age, we get 23, as you might expect. 618 00:26:54,700 --> 00:26:57,760 I was able to update the key. 619 00:26:57,760 --> 00:26:59,950 And you can also delete something from a dictionary 620 00:26:59,950 --> 00:27:02,920 by saying dell is the keyword here. 621 00:27:02,920 --> 00:27:06,730 So for delete-- so if I delete age is Bob, 622 00:27:06,730 --> 00:27:10,980 and now let me just print out the ages. 623 00:27:10,980 --> 00:27:15,720 What I get is Alice is 23 because she had a birthday, 22 to 23. 624 00:27:15,720 --> 00:27:18,000 Charlie is 28, as I said on line three. 625 00:27:18,000 --> 00:27:20,550 But Bob is no longer inside of this dictionary. 626 00:27:20,550 --> 00:27:21,990 Remove that from the dictionary. 627 00:27:21,990 --> 00:27:23,209 Good question. 628 00:27:23,209 --> 00:27:23,750 Other things? 629 00:27:23,750 --> 00:27:24,250 Yeah? 630 00:27:24,250 --> 00:27:28,227 AUDIENCE: [INAUDIBLE] 631 00:27:28,227 --> 00:27:31,125 632 00:27:31,125 --> 00:27:32,160 BRIAN YU: Good question. 633 00:27:32,160 --> 00:27:34,254 So the question is can you only go keys to values, 634 00:27:34,254 --> 00:27:35,670 or can it go the other way around? 635 00:27:35,670 --> 00:27:40,160 Long story, short, the dictionary is only designed to go from key to value. 636 00:27:40,160 --> 00:27:41,910 You look up the key and you get the value. 637 00:27:41,910 --> 00:27:43,350 But certainly, you can write algorithms that 638 00:27:43,350 --> 00:27:45,930 would give you the answer to the question that you're asking. 639 00:27:45,930 --> 00:27:48,477 640 00:27:48,477 --> 00:27:51,310 So it is important to think about which direction you want it to go. 641 00:27:51,310 --> 00:27:53,935 Usually you want what you're looking up to be a key that you're 642 00:27:53,935 --> 00:27:56,050 going to know for sure, and the value is the value 643 00:27:56,050 --> 00:27:57,955 that you care about identifying. 644 00:27:57,955 --> 00:28:01,210 645 00:28:01,210 --> 00:28:01,870 Other things? 646 00:28:01,870 --> 00:28:04,340 647 00:28:04,340 --> 00:28:04,840 All right. 648 00:28:04,840 --> 00:28:06,640 We'll look at a couple more things before we turn 649 00:28:06,640 --> 00:28:08,223 to actually building web applications. 650 00:28:08,223 --> 00:28:10,840 Just want to re-familiarize everyone with Python first. 651 00:28:10,840 --> 00:28:12,310 We'll talk about functions. 652 00:28:12,310 --> 00:28:15,220 And so functions-- I might create a function-- 653 00:28:15,220 --> 00:28:18,940 let me create a new file called functions dot pi. 654 00:28:18,940 --> 00:28:22,380 And let's create a function called square 655 00:28:22,380 --> 00:28:25,890 that just takes a number and squares it, returns the value of x squared. 656 00:28:25,890 --> 00:28:28,329 657 00:28:28,329 --> 00:28:30,620 And that function is going to look something like this. 658 00:28:30,620 --> 00:28:32,180 We define a function called square. 659 00:28:32,180 --> 00:28:35,540 In parentheses is the input that it takes, a variable called x. 660 00:28:35,540 --> 00:28:39,230 And what we return from the function is just a value x times x. 661 00:28:39,230 --> 00:28:41,670 We multiply x by itself. 662 00:28:41,670 --> 00:28:48,630 And now what I'd like to do is print out the square of 10, for instance. 663 00:28:48,630 --> 00:28:51,920 So I'm passing the number 10 as input to the square function, 664 00:28:51,920 --> 00:28:53,290 running that function. 665 00:28:53,290 --> 00:28:55,640 Whoops, wrong file. 666 00:28:55,640 --> 00:29:00,410 Functions dot pi, and I, in fact, get the number 100. 667 00:29:00,410 --> 00:29:03,020 Oftentimes, a common paradigm that you'll see 668 00:29:03,020 --> 00:29:06,560 is whatever the core code of your Python script 669 00:29:06,560 --> 00:29:08,631 does goes inside of a main function. 670 00:29:08,631 --> 00:29:11,630 And you'll often see the main function at the top of the file, actually. 671 00:29:11,630 --> 00:29:14,731 672 00:29:14,731 --> 00:29:17,480 And then at the bottom, you'll see some lines that look like this. 673 00:29:17,480 --> 00:29:22,490 If name equals main, then run the main function. 674 00:29:22,490 --> 00:29:24,590 And what line seven and eight are basically saying 675 00:29:24,590 --> 00:29:28,060 is if name equals main is asking am I running 676 00:29:28,060 --> 00:29:31,070 this file is the script that I'm running, as opposed to the script 677 00:29:31,070 --> 00:29:32,630 that I'm importing elsewhere? 678 00:29:32,630 --> 00:29:35,580 And if so, then go ahead and run the main function. 679 00:29:35,580 --> 00:29:39,050 So if I run this function it's going to produce the same output, 680 00:29:39,050 --> 00:29:40,550 just produce the number 100. 681 00:29:40,550 --> 00:29:43,040 But the reason why I might put things in a main function 682 00:29:43,040 --> 00:29:46,700 separately is because in a separate file now 683 00:29:46,700 --> 00:29:49,580 I could say something like, all right, from my function's 684 00:29:49,580 --> 00:29:54,986 module, this other file located here, let me import the square function. 685 00:29:54,986 --> 00:29:56,360 And then I can do things with it. 686 00:29:56,360 --> 00:30:07,170 Let me for I in range 10, I'll print out I squared is square I. 687 00:30:07,170 --> 00:30:10,230 Basically using a formatted string, taking whatever the value of I is 688 00:30:10,230 --> 00:30:13,830 and saying I that value squared is, and then in curly braces 689 00:30:13,830 --> 00:30:16,140 plugging in a new value, plugging in the value 690 00:30:16,140 --> 00:30:19,290 of applying the square function to the value I 691 00:30:19,290 --> 00:30:21,000 to get whatever the output of that is. 692 00:30:21,000 --> 00:30:25,080 And if I run Python hello dot pi, I end up getting 0 square to 0, 1 squared 693 00:30:25,080 --> 00:30:28,980 is 1, so on and so forth, because I'm able to use the square function defined 694 00:30:28,980 --> 00:30:31,200 elsewhere. 695 00:30:31,200 --> 00:30:34,140 But if in functions dot pi, I hadn't done this main function thing 696 00:30:34,140 --> 00:30:41,640 and I just said OK, let me print out square of 10 at the bottom of it, 697 00:30:41,640 --> 00:30:44,880 and then when I run Python hello dot pi, I'm 698 00:30:44,880 --> 00:30:48,750 going to get this extra 100 printed before any of the stuff 699 00:30:48,750 --> 00:30:50,790 I actually care about in hello dot pi. 700 00:30:50,790 --> 00:30:53,962 Because this 100 happened when I imported functions dot pi, 701 00:30:53,962 --> 00:30:55,920 and it was running the code from top to bottom. 702 00:30:55,920 --> 00:30:59,729 It ended up running this print square of 10 line as well. 703 00:30:59,729 --> 00:31:01,770 So the reason why we put things in main functions 704 00:31:01,770 --> 00:31:04,950 is so that we can import that module into other modules 705 00:31:04,950 --> 00:31:07,170 and still be able to use all those functions. 706 00:31:07,170 --> 00:31:13,080 So if you're wondering why we saw that in CS50, that would be part of why. 707 00:31:13,080 --> 00:31:14,940 Questions about functions? 708 00:31:14,940 --> 00:31:15,595 Yeah? 709 00:31:15,595 --> 00:31:18,505 AUDIENCE: [INAUDIBLE] 710 00:31:18,505 --> 00:31:20,520 BRIAN YU: The F is for formatting. 711 00:31:20,520 --> 00:31:23,299 So the F in print stands for formatted string. 712 00:31:23,299 --> 00:31:26,340 And I use that because I want to be able to use these curly braces to say 713 00:31:26,340 --> 00:31:27,630 plug in some value here. 714 00:31:27,630 --> 00:31:31,080 I want to plug in I and I want to plug in the value of the square of I. 715 00:31:31,080 --> 00:31:34,530 And those are Python values that I want to insert into the string. 716 00:31:34,530 --> 00:31:37,890 If I didn't have the F there and I tried to run this, what I would get 717 00:31:37,890 --> 00:31:42,780 is literally printouts of Curly Brace I squared is Curly Brace square I. 718 00:31:42,780 --> 00:31:45,590 And that's of course, not what I want. 719 00:31:45,590 --> 00:31:46,250 Good question. 720 00:31:46,250 --> 00:31:47,036 Yeah? 721 00:31:47,036 --> 00:31:49,130 AUDIENCE: [INAUDIBLE] 722 00:31:49,130 --> 00:31:56,740 723 00:31:56,740 --> 00:32:01,770 BRIAN YU: So the question is what is exactly if name equals main doing? 724 00:32:01,770 --> 00:32:05,730 What it's doing is it's not going to run the main function unless this 725 00:32:05,730 --> 00:32:07,182 is the script that I am running. 726 00:32:07,182 --> 00:32:09,390 So any code inside the main function, whether they're 727 00:32:09,390 --> 00:32:12,240 print statements or calls to other functions or whatnot, 728 00:32:12,240 --> 00:32:15,630 aren't going to run unless I'm actually running functions dot pi. 729 00:32:15,630 --> 00:32:19,435 And so if I'm importing it, then that code just never is run at all. 730 00:32:19,435 --> 00:32:23,395 AUDIENCE: [INAUDIBLE] 731 00:32:23,395 --> 00:32:28,752 732 00:32:28,752 --> 00:32:31,460 BRIAN YU: If any variables that are set inside the main function, 733 00:32:31,460 --> 00:32:33,860 those are not going to get carried over in the import. 734 00:32:33,860 --> 00:32:34,840 AUDIENCE: [INAUDIBLE] 735 00:32:34,840 --> 00:32:36,282 BRIAN YU: Right, right. 736 00:32:36,282 --> 00:32:38,240 I think there's a question over here somewhere? 737 00:32:38,240 --> 00:32:38,834 Yeah? 738 00:32:38,834 --> 00:32:42,128 AUDIENCE: [INAUDIBLE] 739 00:32:42,128 --> 00:32:55,665 740 00:32:55,665 --> 00:32:56,665 BRIAN YU: Good question. 741 00:32:56,665 --> 00:32:59,230 So the question's about importing things from different locations. 742 00:32:59,230 --> 00:33:00,563 That gets a little bit trickier. 743 00:33:00,563 --> 00:33:03,670 It has to do with sort of where Python is looking for files. 744 00:33:03,670 --> 00:33:05,290 There are ways of getting around it. 745 00:33:05,290 --> 00:33:09,237 You can import from sub-directories or you could sort of go backwards in order 746 00:33:09,237 --> 00:33:10,945 to get something from a parent directory, 747 00:33:10,945 --> 00:33:13,120 and then go into sub-directories. 748 00:33:13,120 --> 00:33:16,675 But that tends to be a little less common, but possible. 749 00:33:16,675 --> 00:33:20,220 750 00:33:20,220 --> 00:33:23,070 So one last thing I'll touch on that we didn't really 751 00:33:23,070 --> 00:33:25,680 get a chance to talk about in CS50, but that's good to know, 752 00:33:25,680 --> 00:33:28,385 is this idea of how to handle these exceptions. 753 00:33:28,385 --> 00:33:30,510 We've seen a lot of exceptions or errors in Python. 754 00:33:30,510 --> 00:33:33,468 We saw the key error when I tried to look up Charlie in the dictionary, 755 00:33:33,468 --> 00:33:34,710 but Charlie didn't exist. 756 00:33:34,710 --> 00:33:38,499 I saw the error that I got when I was trying to compare a string 757 00:33:38,499 --> 00:33:40,540 and an int to see one was greater than the other. 758 00:33:40,540 --> 00:33:41,610 And we dealt with all these things. 759 00:33:41,610 --> 00:33:43,515 There are all sorts of different errors. 760 00:33:43,515 --> 00:33:48,260 A really easy error to create is x equals 5 divided by 0. 761 00:33:48,260 --> 00:33:49,740 Division by 0 is not allowed. 762 00:33:49,740 --> 00:33:51,990 So what's going to happen if I try to divide by 0? 763 00:33:51,990 --> 00:33:56,400 If I try to run Python hello dot pi, I get a special exception that's 764 00:33:56,400 --> 00:33:57,830 just called a zero division error. 765 00:33:57,830 --> 00:33:59,910 It's like, OK, you can't divide by zero. 766 00:33:59,910 --> 00:34:01,150 Sorry about that. 767 00:34:01,150 --> 00:34:06,150 And so what could you do to try and deal with these potential exceptions? 768 00:34:06,150 --> 00:34:08,400 Well, one way you could try and deal with this problem 769 00:34:08,400 --> 00:34:09,960 is to add all these checks. 770 00:34:09,960 --> 00:34:15,420 So if I said OK, x equals 5, y equals 0, z equals x divided by y, 771 00:34:15,420 --> 00:34:19,949 I could write a check to say OK, if y is equal to 0, 772 00:34:19,949 --> 00:34:26,250 then print like, sorry else, then do z is equal to x divided by y. 773 00:34:26,250 --> 00:34:28,679 And we could check for the errors before they happen. 774 00:34:28,679 --> 00:34:33,659 But a common Python paradigm is just to let the exceptions happen and deal 775 00:34:33,659 --> 00:34:36,179 with the exceptions when they come. 776 00:34:36,179 --> 00:34:39,159 And so the syntax for that's going to look something like this. 777 00:34:39,159 --> 00:34:43,020 I'm going to say something like, try z equals x divided by y. 778 00:34:43,020 --> 00:34:45,929 And when I say put everything inside of a try block, what I'm saying 779 00:34:45,929 --> 00:34:47,909 is run this code. 780 00:34:47,909 --> 00:34:49,980 But I'm going to try to run this code. 781 00:34:49,980 --> 00:34:52,739 Like, there might be some sort of exception or error 782 00:34:52,739 --> 00:34:54,630 that comes about when I'm running this code. 783 00:34:54,630 --> 00:34:57,410 So let's just try it and see what happens. 784 00:34:57,410 --> 00:34:59,100 And run it normally. 785 00:34:59,100 --> 00:35:03,490 Except if we get this particular exception, the zero division error, 786 00:35:03,490 --> 00:35:09,997 then go ahead and print out sorry, you can't divide by zero. 787 00:35:09,997 --> 00:35:11,830 So we're saying inside of this except block, 788 00:35:11,830 --> 00:35:15,370 if a zero division error happens and the exception takes place, what is it 789 00:35:15,370 --> 00:35:17,620 that I want to do about that situation? 790 00:35:17,620 --> 00:35:20,910 Well, in this case I just want to print something out. 791 00:35:20,910 --> 00:35:23,910 And so I go Python run this program, and immediately I get sorry, 792 00:35:23,910 --> 00:35:25,191 you can't divide by zero. 793 00:35:25,191 --> 00:35:27,690 Instead of getting some error, like the zero division error, 794 00:35:27,690 --> 00:35:28,750 it just said OK, sorry. 795 00:35:28,750 --> 00:35:30,000 You got a zero division error. 796 00:35:30,000 --> 00:35:33,749 It went down to the except block and then it printed this out. 797 00:35:33,749 --> 00:35:36,290 And so you can imagine that this could be potentially useful. 798 00:35:36,290 --> 00:35:41,120 If we go back to our example from earlier whereby I had ages 799 00:35:41,120 --> 00:35:46,760 and I had Alice was 22 and I had Bob was 27, and I say OK, name. 800 00:35:46,760 --> 00:35:48,500 Let's get some input. 801 00:35:48,500 --> 00:35:51,800 Who do you want to look up? 802 00:35:51,800 --> 00:35:55,340 And I'm going to print out a string. 803 00:35:55,340 --> 00:36:00,820 I'm going to print out name is ages name years old. 804 00:36:00,820 --> 00:36:03,650 I'm printing out someone's name is, and then 805 00:36:03,650 --> 00:36:05,930 looking them up in the age's dictionary with the name 806 00:36:05,930 --> 00:36:08,660 is the key, getting the value, which is the age, 807 00:36:08,660 --> 00:36:10,370 name is this number of years old. 808 00:36:10,370 --> 00:36:11,820 And let's print that out. 809 00:36:11,820 --> 00:36:13,035 And so I try that. 810 00:36:13,035 --> 00:36:14,160 Who do you want to look up? 811 00:36:14,160 --> 00:36:15,700 I want to look up Alice. 812 00:36:15,700 --> 00:36:16,790 Alice is 22 years old. 813 00:36:16,790 --> 00:36:17,290 Great. 814 00:36:17,290 --> 00:36:18,260 I want to look up Bob. 815 00:36:18,260 --> 00:36:19,370 Bob is 27 years old. 816 00:36:19,370 --> 00:36:21,650 All right, I want to look up Charlie. 817 00:36:21,650 --> 00:36:22,571 Key error, Charlie. 818 00:36:22,571 --> 00:36:24,070 This is the key error we saw before. 819 00:36:24,070 --> 00:36:25,650 Charlie is not in the dictionary. 820 00:36:25,650 --> 00:36:28,560 So when I try to look up Charlie, it doesn't quite work. 821 00:36:28,560 --> 00:36:30,350 So how can I deal with the situation? 822 00:36:30,350 --> 00:36:32,750 Well, one way I could deal with it is OK, 823 00:36:32,750 --> 00:36:41,480 if the name is in the age's dictionary, then print it out, else, print sorry, 824 00:36:41,480 --> 00:36:44,630 name is not in the dictionary or in the-- 825 00:36:44,630 --> 00:36:47,020 826 00:36:47,020 --> 00:36:47,520 yeah. 827 00:36:47,520 --> 00:36:51,439 It's not in the dictionary and make that a formatted string. 828 00:36:51,439 --> 00:36:52,230 So I could do that. 829 00:36:52,230 --> 00:36:55,530 If name and ages is asking is this person's name 830 00:36:55,530 --> 00:37:00,580 inside of this dictionary of ages, and if I run this and type in Charlie, 831 00:37:00,580 --> 00:37:02,820 I get OK, sorry, Charlie is not in the dictionary. 832 00:37:02,820 --> 00:37:04,620 But a more efficient and what I might call 833 00:37:04,620 --> 00:37:09,450 a more Pythonic way of writing the same code is just to say you know what? 834 00:37:09,450 --> 00:37:10,320 Try to do this. 835 00:37:10,320 --> 00:37:13,890 Try to print out this name is this number of years old. 836 00:37:13,890 --> 00:37:17,280 Except if we get a key error, then that must 837 00:37:17,280 --> 00:37:21,590 mean that we couldn't find the person's name in this dictionary of ages 838 00:37:21,590 --> 00:37:22,590 that we were looking up. 839 00:37:22,590 --> 00:37:25,789 And we can say OK, sorry, this person's name is not in the dictionary. 840 00:37:25,789 --> 00:37:27,080 Sit around Python hello dot pi. 841 00:37:27,080 --> 00:37:28,205 Who do you want to look up? 842 00:37:28,205 --> 00:37:29,920 We want to look up Charlie. 843 00:37:29,920 --> 00:37:33,350 OK, sorry, Charlie is not the dictionary. 844 00:37:33,350 --> 00:37:36,430 And so this exception handling mechanism is something 845 00:37:36,430 --> 00:37:39,030 you'll see quite frequently in Python. 846 00:37:39,030 --> 00:37:41,530 Python is designed to let you take advantage of this feature 847 00:37:41,530 --> 00:37:43,229 very readily and very easily. 848 00:37:43,229 --> 00:37:45,520 And so you'll often see people try and deal with errors 849 00:37:45,520 --> 00:37:47,920 in this particular way of just trying code and then 850 00:37:47,920 --> 00:37:49,240 catching that error if need be. 851 00:37:49,240 --> 00:37:49,740 Yeah? 852 00:37:49,740 --> 00:37:53,142 AUDIENCE: [INAUDIBLE] 853 00:37:53,142 --> 00:37:54,210 BRIAN YU: Good question. 854 00:37:54,210 --> 00:37:57,800 The question is, do you need to define what type of error you're looking for? 855 00:37:57,800 --> 00:38:00,320 You can be less specific if you want. 856 00:38:00,320 --> 00:38:03,620 I'm being very specific in saying when you get a key error exception, 857 00:38:03,620 --> 00:38:05,119 you should deal with it in this way. 858 00:38:05,119 --> 00:38:09,080 But you could generalize it to say except any sort of general exception 859 00:38:09,080 --> 00:38:10,860 in order to catch errors more broadly. 860 00:38:10,860 --> 00:38:12,200 But then you need to figure out a way of dealing 861 00:38:12,200 --> 00:38:14,160 with many numbers of different kinds of errors. 862 00:38:14,160 --> 00:38:15,910 So generally, if you can be specific, it's 863 00:38:15,910 --> 00:38:20,014 a good idea to be specific about what it is that went wrong. 864 00:38:20,014 --> 00:38:20,514 Yeah? 865 00:38:20,514 --> 00:38:23,986 AUDIENCE: [INAUDIBLE] 866 00:38:23,986 --> 00:38:26,466 867 00:38:26,466 --> 00:38:27,240 BRIAN YU: Yeah. 868 00:38:27,240 --> 00:38:28,374 So we could do-- 869 00:38:28,374 --> 00:38:30,540 so the question is what if I wanted to differentiate 870 00:38:30,540 --> 00:38:32,920 based on two different types of errors? 871 00:38:32,920 --> 00:38:35,250 So let's do a key error. 872 00:38:35,250 --> 00:38:39,750 So name is this number of years old. 873 00:38:39,750 --> 00:38:52,460 And let's say for whatever reason I wanted to set x to 10 divided by age 874 00:38:52,460 --> 00:38:53,430 is name. 875 00:38:53,430 --> 00:38:54,500 I don't know why you would want to do this. 876 00:38:54,500 --> 00:38:56,090 I'm just sort of creating a contrived example where 877 00:38:56,090 --> 00:38:57,780 we might get two types of errors. 878 00:38:57,780 --> 00:38:59,870 But the type of error we might reasonably get here 879 00:38:59,870 --> 00:39:01,130 is a zero division error. 880 00:39:01,130 --> 00:39:05,819 If for instance Charlie is 0 years old, and I said OK, run Python. 881 00:39:05,819 --> 00:39:06,860 Who do I want to look up? 882 00:39:06,860 --> 00:39:07,580 Alice. 883 00:39:07,580 --> 00:39:09,140 Alice is 22. 884 00:39:09,140 --> 00:39:13,010 If I look up someone who's not in the dictionary like David, I get sorry, 885 00:39:13,010 --> 00:39:14,390 David it's not the dictionary. 886 00:39:14,390 --> 00:39:18,080 But if I look up Charlie, I get Charlie is 0 years old, 887 00:39:18,080 --> 00:39:21,180 but then I get to zero division error, a different type of exception. 888 00:39:21,180 --> 00:39:22,740 And I can handle that separately. 889 00:39:22,740 --> 00:39:28,460 I can say except zero division error and print sorry, 890 00:39:28,460 --> 00:39:32,300 the age is 0 or something like that, handle both of those exceptions. 891 00:39:32,300 --> 00:39:36,280 So now if I type in David, I get sorry, David is not the dictionary. 892 00:39:36,280 --> 00:39:39,800 But I type in Charlie, and I get Charlie is 0 years old. 893 00:39:39,800 --> 00:39:42,620 And then instead of getting a zero division error, I get sorry, 894 00:39:42,620 --> 00:39:43,430 the age is 0. 895 00:39:43,430 --> 00:39:45,409 So you can chain these except blocks together. 896 00:39:45,409 --> 00:39:47,450 It's saying if I get this type of error, do this. 897 00:39:47,450 --> 00:39:49,560 If I get that type of error, do something else. 898 00:39:49,560 --> 00:39:51,930 And so you can exception handle in that way as well. 899 00:39:51,930 --> 00:39:54,911 900 00:39:54,911 --> 00:39:55,410 All right. 901 00:39:55,410 --> 00:39:56,670 Covered a lot of topics just now. 902 00:39:56,670 --> 00:39:58,200 How do we feel about that generally? 903 00:39:58,200 --> 00:40:01,980 904 00:40:01,980 --> 00:40:03,450 All right, mostly feeling good. 905 00:40:03,450 --> 00:40:04,740 Fantastic. 906 00:40:04,740 --> 00:40:06,840 In that case, let's go ahead and turn to Flask. 907 00:40:06,840 --> 00:40:08,700 A question first before we turn to Flask. 908 00:40:08,700 --> 00:40:13,146 AUDIENCE: [INAUDIBLE] 909 00:40:13,146 --> 00:40:17,580 910 00:40:17,580 --> 00:40:18,580 BRIAN YU: Good question. 911 00:40:18,580 --> 00:40:21,663 So the question is what if I want to do more code after all this exception 912 00:40:21,663 --> 00:40:22,300 handling? 913 00:40:22,300 --> 00:40:25,299 You can just add it after that tries and excepts are done and just don't 914 00:40:25,299 --> 00:40:26,200 indent them. 915 00:40:26,200 --> 00:40:28,442 I can say this is the end of the program. 916 00:40:28,442 --> 00:40:30,650 And then no matter what happens, if it works, I type, 917 00:40:30,650 --> 00:40:31,630 what do you want to look up? 918 00:40:31,630 --> 00:40:32,250 Alice. 919 00:40:32,250 --> 00:40:33,100 Alice is 22. 920 00:40:33,100 --> 00:40:34,420 This is the end of the program. 921 00:40:34,420 --> 00:40:35,320 I look up David. 922 00:40:35,320 --> 00:40:36,580 David's not the dictionary. 923 00:40:36,580 --> 00:40:38,120 Still get to the end of the program. 924 00:40:38,120 --> 00:40:40,161 So any code after that try except will still run. 925 00:40:40,161 --> 00:40:42,870 926 00:40:42,870 --> 00:40:43,440 Other things? 927 00:40:43,440 --> 00:40:46,400 928 00:40:46,400 --> 00:40:49,300 All right, so let's go ahead and create a Flask application. 929 00:40:49,300 --> 00:40:52,070 And so recall that Flask was a Python framework 930 00:40:52,070 --> 00:40:55,910 that we can use to very easily and very quickly build web applications 931 00:40:55,910 --> 00:40:57,110 and begin to scale down. 932 00:40:57,110 --> 00:40:57,610 Yeah? 933 00:40:57,610 --> 00:40:59,615 AUDIENCE: [INAUDIBLE] 934 00:40:59,615 --> 00:41:02,010 BRIAN YU: Yeah sure. 935 00:41:02,010 --> 00:41:03,800 Hello dot pi. 936 00:41:03,800 --> 00:41:06,469 And if you want to see this as well, I haven't yet 937 00:41:06,469 --> 00:41:08,510 posted the source code examples for this morning, 938 00:41:08,510 --> 00:41:12,260 but I will soon as soon as we're done with this morning session. 939 00:41:12,260 --> 00:41:15,600 940 00:41:15,600 --> 00:41:16,100 All right. 941 00:41:16,100 --> 00:41:19,040 So Flask is what we're going to use in order to build web applications. 942 00:41:19,040 --> 00:41:20,456 We saw a little bit of it in CS50. 943 00:41:20,456 --> 00:41:24,530 But we're really going to dive more into it today and tomorrow, in particular, 944 00:41:24,530 --> 00:41:26,570 and the day after as well. 945 00:41:26,570 --> 00:41:30,350 And so in order to create a Flask application, 946 00:41:30,350 --> 00:41:33,610 we're going to store code in a file called application dot pi. 947 00:41:33,610 --> 00:41:36,110 And the simplest of Flask applications, as you might recall, 948 00:41:36,110 --> 00:41:38,939 looks something like this, from Flask import Flask-- 949 00:41:38,939 --> 00:41:40,980 so you'll need to install Flask on your computer. 950 00:41:40,980 --> 00:41:42,771 If you have the Python Package Manager, you 951 00:41:42,771 --> 00:41:48,650 can just write PIP or PIP3 install Flask to install flask under your system. 952 00:41:48,650 --> 00:41:52,620 And I'm going to say app equals Flask name. 953 00:41:52,620 --> 00:41:55,830 In other words, create a Flask app from this file. 954 00:41:55,830 --> 00:41:58,950 I want this file to be the host for a Flask application. 955 00:41:58,950 --> 00:42:03,360 And the entire internet is based on this idea of routing, the idea 956 00:42:03,360 --> 00:42:08,100 that if I go to some website slash a particular route, that 957 00:42:08,100 --> 00:42:11,130 takes me to some different logic on that website. 958 00:42:11,130 --> 00:42:13,440 If you go to CS50 dot Harvard dot edu you 959 00:42:13,440 --> 00:42:15,660 get the normal CS50 college web page. 960 00:42:15,660 --> 00:42:19,530 But if you go to CS50 dot Harvard dot edu slash beyond, go to the slash 961 00:42:19,530 --> 00:42:22,170 beyond route, then you're taken to this course's web page. 962 00:42:22,170 --> 00:42:24,960 And so depending on your route, different logic happens, 963 00:42:24,960 --> 00:42:26,710 the user sees different content. 964 00:42:26,710 --> 00:42:29,340 And so the entirety of Flask is based on this idea 965 00:42:29,340 --> 00:42:32,070 that if different routes happen, we should be running 966 00:42:32,070 --> 00:42:34,290 different code or different functions. 967 00:42:34,290 --> 00:42:38,550 And so I'm going to say at app dot route slash. 968 00:42:38,550 --> 00:42:41,520 In other words, if I just go to the slash route, 969 00:42:41,520 --> 00:42:44,220 what is the code that should run here? 970 00:42:44,220 --> 00:42:48,850 And I'll say OK, we'll run a function that I'm just going to call index. 971 00:42:48,850 --> 00:42:49,900 Could be called anything. 972 00:42:49,900 --> 00:42:51,430 The function name is sort of irrelevant, that you 973 00:42:51,430 --> 00:42:54,580 can reference things by it, which we'll maybe see a little bit later. 974 00:42:54,580 --> 00:42:58,930 And here I can say OK, return hello world. 975 00:42:58,930 --> 00:43:01,450 Very simple, very basic web application that's 976 00:43:01,450 --> 00:43:05,050 basically saying if someone goes to the slash route of my web application, 977 00:43:05,050 --> 00:43:07,410 I want to say hello world to them. 978 00:43:07,410 --> 00:43:11,010 I can run this application by running Flask run. 979 00:43:11,010 --> 00:43:12,660 And so I run Flask run. 980 00:43:12,660 --> 00:43:14,230 I end up getting this URL. 981 00:43:14,230 --> 00:43:18,180 I'll go out and copy this URL, paste it into a web browser. 982 00:43:18,180 --> 00:43:19,500 And what I see is hello world. 983 00:43:19,500 --> 00:43:21,000 I didn't go to any particular route. 984 00:43:21,000 --> 00:43:25,320 I just went to the default route, and I get hello world as a result. 985 00:43:25,320 --> 00:43:27,960 Now of course, I could add other routes to this as well. 986 00:43:27,960 --> 00:43:31,170 If I wanted to, for instance, add a route that didn't just say hello world, 987 00:43:31,170 --> 00:43:34,197 but said hello to someone in particular like Julia, for example-- 988 00:43:34,197 --> 00:43:35,780 Julia is sitting right in front of me. 989 00:43:35,780 --> 00:43:41,040 So she's in all my examples today-- app dot route slash Julia for instance, 990 00:43:41,040 --> 00:43:43,350 I can run a special function which is called Julia 991 00:43:43,350 --> 00:43:47,200 that's going to return hello Julia. 992 00:43:47,200 --> 00:43:48,990 And so if I run this web application now-- 993 00:43:48,990 --> 00:43:50,580 I'll go ahead and restart it-- 994 00:43:50,580 --> 00:43:53,200 or it probably restarts automatically-- 995 00:43:53,200 --> 00:43:56,860 but I refresh the page and it still says hello world. 996 00:43:56,860 --> 00:43:59,760 But if I change the URL, instead of just going to the default route, 997 00:43:59,760 --> 00:44:04,830 I go to the slash Julia route and press Return, then I get a different page. 998 00:44:04,830 --> 00:44:08,250 This page says hello Julia instead. 999 00:44:08,250 --> 00:44:12,210 So two different routes, each of which is connected to a different function. 1000 00:44:12,210 --> 00:44:15,140 And each function return some different information 1001 00:44:15,140 --> 00:44:18,094 that gets sent back to the user who's viewing the page. 1002 00:44:18,094 --> 00:44:19,260 Questions about that so far? 1003 00:44:19,260 --> 00:44:23,432 That much at least should be review from CS50. 1004 00:44:23,432 --> 00:44:25,640 Now of course, there's a little bit of a problem here 1005 00:44:25,640 --> 00:44:27,545 in that this is not a particularly scalable solution. 1006 00:44:27,545 --> 00:44:29,850 So like, Athena just walked in the door, for instance. 1007 00:44:29,850 --> 00:44:31,683 And if I wanted to say hi to Athena, I might 1008 00:44:31,683 --> 00:44:35,840 want to go to this web application and go to web address slash Athena. 1009 00:44:35,840 --> 00:44:38,960 But when I do so, I get a 404 error, not found. 1010 00:44:38,960 --> 00:44:42,200 And I got this error because slash Athena is not a route on my website. 1011 00:44:42,200 --> 00:44:44,205 I can't go to slash Athena because I haven't 1012 00:44:44,205 --> 00:44:47,330 written a rule that says when I go to slash Athena, what code should I run? 1013 00:44:47,330 --> 00:44:49,220 What should I actually do? 1014 00:44:49,220 --> 00:44:52,820 So we can generalize this idea of instead 1015 00:44:52,820 --> 00:44:56,000 of just having a slash Julia route the just says hello to Julia, 1016 00:44:56,000 --> 00:45:00,160 maybe I want to be able to handle not just fixed routes, but variable routes, 1017 00:45:00,160 --> 00:45:03,500 routes that take in some variable as their argument, 1018 00:45:03,500 --> 00:45:05,990 and then produce some sort of different output. 1019 00:45:05,990 --> 00:45:09,590 And so rather than just saying this is the route that is slash Julia, 1020 00:45:09,590 --> 00:45:14,000 I'll say this is a route that's going to take a string value, 1021 00:45:14,000 --> 00:45:16,680 and I'm just going to call it name. 1022 00:45:16,680 --> 00:45:19,470 This function is going to be called hello instead of just Julia. 1023 00:45:19,470 --> 00:45:20,700 And hello is going to take an argument. 1024 00:45:20,700 --> 00:45:22,533 It's going to take the argument called name, 1025 00:45:22,533 --> 00:45:28,297 where this name matches up with the variable that's inside of the route. 1026 00:45:28,297 --> 00:45:30,630 And so what I'm doing here is creating a variable route. 1027 00:45:30,630 --> 00:45:32,910 This isn't just going to accept slash Julia, 1028 00:45:32,910 --> 00:45:35,906 but it's going to accept slash any string. 1029 00:45:35,906 --> 00:45:37,530 That string is going to be called name. 1030 00:45:37,530 --> 00:45:42,100 And that value name is going to be passed in to the hello function. 1031 00:45:42,100 --> 00:45:47,080 And so now, rather than returning hello Julia, I can return hello 1032 00:45:47,080 --> 00:45:52,930 and then a formatted string plugging in that name into that spot in the string. 1033 00:45:52,930 --> 00:45:54,999 And so OK, what does that going to do? 1034 00:45:54,999 --> 00:45:56,790 Let's go ahead and run the web application. 1035 00:45:56,790 --> 00:45:58,330 I go to slash Athena. 1036 00:45:58,330 --> 00:45:59,890 And it says hello Athena. 1037 00:45:59,890 --> 00:46:02,890 It's taking the route that I plugged into this URL, 1038 00:46:02,890 --> 00:46:06,642 and it's just placing it into the formatted string that 1039 00:46:06,642 --> 00:46:07,600 gets shown to the user. 1040 00:46:07,600 --> 00:46:10,750 I type in slash Josh instead, and it says hello Josh. 1041 00:46:10,750 --> 00:46:13,790 I type in slash Krishna, it says hello Krishna. 1042 00:46:13,790 --> 00:46:15,880 And so I can do this with any string. 1043 00:46:15,880 --> 00:46:19,520 And it's just going to give me the result here on that page. 1044 00:46:19,520 --> 00:46:22,759 Now of course, this isn't quite ideal because I would probably 1045 00:46:22,759 --> 00:46:24,300 like for the names to be capitalized. 1046 00:46:24,300 --> 00:46:26,510 It would look a little nicer for the user interface. 1047 00:46:26,510 --> 00:46:27,176 But that's fine. 1048 00:46:27,176 --> 00:46:29,590 I can use any Python logic I want in order 1049 00:46:29,590 --> 00:46:31,780 to be able to generate the page that I want. 1050 00:46:31,780 --> 00:46:35,230 So I could do something like name equals name dot capitalize. 1051 00:46:35,230 --> 00:46:37,720 And I happen to know the Python has a built in function 1052 00:46:37,720 --> 00:46:42,370 called capitalize that takes a string and capitalizes it. 1053 00:46:42,370 --> 00:46:43,480 So I do that. 1054 00:46:43,480 --> 00:46:45,580 And when I go to slash Krishna now, now I 1055 00:46:45,580 --> 00:46:51,950 get OK, capital K. I go to slash Athena, capital A, Athena. 1056 00:46:51,950 --> 00:46:54,370 And so here here's the web application that's doing that. 1057 00:46:54,370 --> 00:46:58,060 I have a variable root that accepts some arbitrary string that's its input. 1058 00:46:58,060 --> 00:47:00,210 And I can go to that arbitrary string. 1059 00:47:00,210 --> 00:47:03,340 And when I do so, we're able to take some variable, 1060 00:47:03,340 --> 00:47:06,670 make some modifications to it using any arbitrary Python logic we want, 1061 00:47:06,670 --> 00:47:12,500 capitalizing some name, for example, and then returning that result. 1062 00:47:12,500 --> 00:47:13,700 Questions about that? 1063 00:47:13,700 --> 00:47:14,200 Yeah? 1064 00:47:14,200 --> 00:47:17,180 AUDIENCE: [INAUDIBLE] 1065 00:47:17,180 --> 00:47:18,500 BRIAN YU: Great question! 1066 00:47:18,500 --> 00:47:20,780 Question is if I still had a slash Athena route, 1067 00:47:20,780 --> 00:47:22,490 which one is it going to do? 1068 00:47:22,490 --> 00:47:26,780 So let's say I have an app dot route slash Athena that actually 1069 00:47:26,780 --> 00:47:29,630 is an Athena route, definitely Athena. 1070 00:47:29,630 --> 00:47:33,544 And this one returns some other content. 1071 00:47:33,544 --> 00:47:34,460 I don't know what yet. 1072 00:47:34,460 --> 00:47:36,470 But at the end, it gets some other content. 1073 00:47:36,470 --> 00:47:37,340 She likes otters. 1074 00:47:37,340 --> 00:47:40,040 Athena gets otters. 1075 00:47:40,040 --> 00:47:41,210 This is the other one. 1076 00:47:41,210 --> 00:47:43,580 So now what's going to happen if I go to slash Athena? 1077 00:47:43,580 --> 00:47:45,590 Am I going to get hello comma name? 1078 00:47:45,590 --> 00:47:48,549 Or am I going to get some other content Athena likes otters? 1079 00:47:48,549 --> 00:47:50,840 Well, Flask is going to try to be intelligent about it. 1080 00:47:50,840 --> 00:47:54,950 Flask is going to go to the more specific route if it can. 1081 00:47:54,950 --> 00:47:58,590 And so therefore, if I go to Athena, what I get is some other content 1082 00:47:58,590 --> 00:47:59,660 Athena likes otters. 1083 00:47:59,660 --> 00:48:03,350 That is the more specific route, as opposed to the more general one, 1084 00:48:03,350 --> 00:48:05,545 if we just went to the slash name one. 1085 00:48:05,545 --> 00:48:08,170 So if I go to slash Julia, Julia does not like otters. 1086 00:48:08,170 --> 00:48:09,710 It just says hello Julia. 1087 00:48:09,710 --> 00:48:13,250 I don't know if Julia likes otters or not, but it's what we get. 1088 00:48:13,250 --> 00:48:14,539 Good question though. 1089 00:48:14,539 --> 00:48:15,080 Other things? 1090 00:48:15,080 --> 00:48:15,720 Yeah? 1091 00:48:15,720 --> 00:48:18,668 AUDIENCE: So when you find a variable [INAUDIBLE]?? 1092 00:48:18,668 --> 00:48:27,117 1093 00:48:27,117 --> 00:48:28,200 BRIAN YU: Good question. 1094 00:48:28,200 --> 00:48:30,270 So the question is like, what is this string doing here? 1095 00:48:30,270 --> 00:48:31,230 Does it need to be there? 1096 00:48:31,230 --> 00:48:32,271 It does need to be there. 1097 00:48:32,271 --> 00:48:35,152 So we do need to define what the type of the argument is. 1098 00:48:35,152 --> 00:48:37,110 And the idea here is that that's going to allow 1099 00:48:37,110 --> 00:48:39,540 us to be able to be more specific about our routes, 1100 00:48:39,540 --> 00:48:42,840 that sometimes we might want for example, an int to be there, 1101 00:48:42,840 --> 00:48:47,290 where you imagine a newspaper website for example, 1102 00:48:47,290 --> 00:48:50,550 and you want to go to yesterday's paper, you might go to like, 1103 00:48:50,550 --> 00:48:55,680 name of the newspaper.com slash 2019 slash one slash whatever the date is. 1104 00:48:55,680 --> 00:48:58,177 You have some custom route that does that. 1105 00:48:58,177 --> 00:49:00,510 And you can imagine that this variable routing gives you 1106 00:49:00,510 --> 00:49:02,520 a lot of expressive capability that we couldn't 1107 00:49:02,520 --> 00:49:04,800 have with just fixed routes where you imagine 1108 00:49:04,800 --> 00:49:08,600 that sites like Twitter or Facebook, for instance, where you go to Twitter.com 1109 00:49:08,600 --> 00:49:10,472 slash the person's Twitter handle. 1110 00:49:10,472 --> 00:49:12,180 Twitter doesn't have some engineer that's 1111 00:49:12,180 --> 00:49:15,150 writing out routes for every single possible user on Twitter. 1112 00:49:15,150 --> 00:49:18,150 They just have some variable route that accepts any user name. 1113 00:49:18,150 --> 00:49:20,460 And when any user name is typed in, it runs some logic 1114 00:49:20,460 --> 00:49:24,500 in order to process that user name and handle it appropriately. 1115 00:49:24,500 --> 00:49:25,100 Good question. 1116 00:49:25,100 --> 00:49:25,600 Yeah? 1117 00:49:25,600 --> 00:49:27,597 AUDIENCE: [INAUDIBLE] 1118 00:49:27,597 --> 00:49:36,888 1119 00:49:36,888 --> 00:49:38,010 BRIAN YU: Good question. 1120 00:49:38,010 --> 00:49:41,790 So question is what if I wanted to have multiple variables inside 1121 00:49:41,790 --> 00:49:43,080 of this route? 1122 00:49:43,080 --> 00:49:44,410 Pretty easy to do. 1123 00:49:44,410 --> 00:49:48,540 You can just say if I want to rather than just saying hello to one person, 1124 00:49:48,540 --> 00:49:54,070 say hello to two people, I can do string name one and slash string name two. 1125 00:49:54,070 --> 00:49:57,750 A little bit of a probably not intuitive user interface for these URLs, 1126 00:49:57,750 --> 00:49:58,920 but that's fine. 1127 00:49:58,920 --> 00:50:00,189 Name one and name two-- 1128 00:50:00,189 --> 00:50:01,980 we'll go ahead and capitalize both of them. 1129 00:50:01,980 --> 00:50:04,820 Name two equals name two dot capitalize. 1130 00:50:04,820 --> 00:50:07,100 And we'll need to capitalize name one as well. 1131 00:50:07,100 --> 00:50:12,030 And we'll say hello name one and name two. 1132 00:50:12,030 --> 00:50:15,120 And so now I have slash some string slash them other string. 1133 00:50:15,120 --> 00:50:17,560 They're both arguments to this function. 1134 00:50:17,560 --> 00:50:20,610 And if I run this again, go to just slash Julia. 1135 00:50:20,610 --> 00:50:21,540 OK, not found. 1136 00:50:21,540 --> 00:50:24,840 There is no longer a route that's just slash some arbitrary string. 1137 00:50:24,840 --> 00:50:29,160 The only routes that I have are the slash Athena and slash two names. 1138 00:50:29,160 --> 00:50:31,170 I have to go slash Julia slash Athena. 1139 00:50:31,170 --> 00:50:34,510 And then I get OK, hello Julia and Athena. 1140 00:50:34,510 --> 00:50:35,200 Other questions? 1141 00:50:35,200 --> 00:50:35,700 Yes? 1142 00:50:35,700 --> 00:50:37,065 AUDIENCE: [INAUDIBLE] 1143 00:50:37,065 --> 00:50:38,880 BRIAN YU: What about optional arguments? 1144 00:50:38,880 --> 00:50:40,920 Great question. 1145 00:50:40,920 --> 00:50:45,390 So the situation might arise in which you don't always 1146 00:50:45,390 --> 00:50:47,130 need something to be there. 1147 00:50:47,130 --> 00:50:51,780 So maybe by default, if someone only gave me one name 1148 00:50:51,780 --> 00:50:54,810 but didn't give me a second name, I just always want 1149 00:50:54,810 --> 00:50:57,090 to say hi to Josh no matter what. 1150 00:50:57,090 --> 00:51:00,390 And so I might come up with a situation where a particular function 1151 00:51:00,390 --> 00:51:02,550 has two routes that can get to it. 1152 00:51:02,550 --> 00:51:06,930 I can say OK, maybe I provide string name one and name two, 1153 00:51:06,930 --> 00:51:09,360 or maybe I just provide name one. 1154 00:51:09,360 --> 00:51:12,010 Either way, I still want to run this code. 1155 00:51:12,010 --> 00:51:18,522 But if I ran this route here on line 10, just providing a single name, name one, 1156 00:51:18,522 --> 00:51:20,730 then on line 11 when I try to run the hello function, 1157 00:51:20,730 --> 00:51:23,980 name two is not going to have a value. 1158 00:51:23,980 --> 00:51:26,010 And so I can give names two a default value. 1159 00:51:26,010 --> 00:51:31,090 I can say all right, name two by default, is going to be Josh. 1160 00:51:31,090 --> 00:51:33,140 And so what happens now? 1161 00:51:33,140 --> 00:51:38,102 Now if I just go to Julia, press Return, I get hello Julia and Josh. 1162 00:51:38,102 --> 00:51:40,310 I didn't provide a second name, so it's automatically 1163 00:51:40,310 --> 00:51:42,143 going to fill in Josh no matter what I type. 1164 00:51:42,143 --> 00:51:43,176 I type in slash Krishna. 1165 00:51:43,176 --> 00:51:45,050 And it's going to say hello Krishna and Josh, 1166 00:51:45,050 --> 00:51:47,330 automatically putting Josh there every single time. 1167 00:51:47,330 --> 00:51:50,600 And it's not unless I give it a second name, say Krishna slash Athena, 1168 00:51:50,600 --> 00:51:53,180 then now it's going to say hello Krishna and Athena, 1169 00:51:53,180 --> 00:51:56,450 filling in Athena as the variable for the second name. 1170 00:51:56,450 --> 00:52:00,320 So you have this ability to give a default value to a variable 1171 00:52:00,320 --> 00:52:01,532 if you so choose to do so. 1172 00:52:01,532 --> 00:52:02,990 And this is not true of just Flask. 1173 00:52:02,990 --> 00:52:04,889 You can give default arguments to functions 1174 00:52:04,889 --> 00:52:06,680 anytime you're writing functions in Python. 1175 00:52:06,680 --> 00:52:09,240 And you can find that that can sometimes be helpful. 1176 00:52:09,240 --> 00:52:09,740 Yeah? 1177 00:52:09,740 --> 00:52:12,160 AUDIENCE: [INAUDIBLE] 1178 00:52:12,160 --> 00:52:13,160 BRIAN YU: Good question. 1179 00:52:13,160 --> 00:52:15,650 Does it allow regular expressions? 1180 00:52:15,650 --> 00:52:17,070 I don't believe Flask does. 1181 00:52:17,070 --> 00:52:20,120 1182 00:52:20,120 --> 00:52:23,270 There is a similar framework to Flask called Django, a little bit heavier 1183 00:52:23,270 --> 00:52:25,850 weight, a little bit more full featured, that does this, 1184 00:52:25,850 --> 00:52:27,740 but with a little more sophistication. 1185 00:52:27,740 --> 00:52:30,860 And Django does allow for regular expression-based patterning 1186 00:52:30,860 --> 00:52:33,670 based on those routes? 1187 00:52:33,670 --> 00:52:34,170 Yeah? 1188 00:52:34,170 --> 00:52:37,978 AUDIENCE: [INAUDIBLE] 1189 00:52:37,978 --> 00:52:38,790 BRIAN YU: Oh! 1190 00:52:38,790 --> 00:52:39,570 Good question. 1191 00:52:39,570 --> 00:52:43,920 What's the significance of the at symbol in at app dot route? 1192 00:52:43,920 --> 00:52:45,720 What is it exactly doing here? 1193 00:52:45,720 --> 00:52:47,452 This is what we call a Python decorator. 1194 00:52:47,452 --> 00:52:50,160 There is an example of the decorators in the source code examples 1195 00:52:50,160 --> 00:52:51,905 that we won't get to today. 1196 00:52:51,905 --> 00:52:54,280 But basically what it's doing is it's taking the function 1197 00:52:54,280 --> 00:52:56,820 and then wrapping the function in some additional logic. 1198 00:52:56,820 --> 00:52:59,210 And the logic it's wrapping it in his logic that says 1199 00:52:59,210 --> 00:53:00,960 listen for someone who goes to this route. 1200 00:53:00,960 --> 00:53:03,450 And if you go to the route, then run this function. 1201 00:53:03,450 --> 00:53:05,460 So it's a Python decorator is what that is. 1202 00:53:05,460 --> 00:53:08,060 1203 00:53:08,060 --> 00:53:08,730 Other things? 1204 00:53:08,730 --> 00:53:09,230 Yeah? 1205 00:53:09,230 --> 00:53:11,910 AUDIENCE: [INAUDIBLE] 1206 00:53:11,910 --> 00:53:14,240 BRIAN YU: Can the default variable be none? 1207 00:53:14,240 --> 00:53:17,300 Yes, the value of variable can be none. 1208 00:53:17,300 --> 00:53:18,500 Name two could be none. 1209 00:53:18,500 --> 00:53:21,289 But the situation you'll get there is, well, we're 1210 00:53:21,289 --> 00:53:24,080 going to get an error in this case, because I go to slash Krishna-- 1211 00:53:24,080 --> 00:53:27,020 I'm going to get an error because you can't capitalize the none 1212 00:53:27,020 --> 00:53:30,359 type is the error that we'll get. 1213 00:53:30,359 --> 00:53:32,900 But yes, you could, in theory, use none as the default value. 1214 00:53:32,900 --> 00:53:35,244 1215 00:53:35,244 --> 00:53:35,910 All right, yeah? 1216 00:53:35,910 --> 00:53:39,179 AUDIENCE: [INAUDIBLE] 1217 00:53:39,179 --> 00:53:40,580 1218 00:53:40,580 --> 00:53:41,290 BRIAN YU: Yep. 1219 00:53:41,290 --> 00:53:43,044 You'll need to have Flask installed. 1220 00:53:43,044 --> 00:53:46,210 But once you have Flask installed, what you can do via probably PIP3 install 1221 00:53:46,210 --> 00:53:50,590 Flask to install Flask, you should be able to Flask run in the directory that 1222 00:53:50,590 --> 00:53:52,210 has application dot pi. 1223 00:53:52,210 --> 00:53:55,010 And then that will start up the web application. 1224 00:53:55,010 --> 00:53:58,570 You might need to set the Flask app. 1225 00:53:58,570 --> 00:54:02,760 So expert Flask app equals application dot pi, 1226 00:54:02,760 --> 00:54:05,260 if it's not able to find which Flask app it should be using. 1227 00:54:05,260 --> 00:54:08,010 So you might want to try that line if things aren't quite working. 1228 00:54:08,010 --> 00:54:11,911 But a TS can come help you if you're having trouble with that as well. 1229 00:54:11,911 --> 00:54:12,410 All right. 1230 00:54:12,410 --> 00:54:15,368 A couple other things I want to talk about before we get to the project 1231 00:54:15,368 --> 00:54:17,170 that we're going to be working on today. 1232 00:54:17,170 --> 00:54:19,600 One is this idea of templates. 1233 00:54:19,600 --> 00:54:23,590 And so oftentimes, instead of just returning a string like hello world, 1234 00:54:23,590 --> 00:54:26,560 I want to return an actual HTML file. 1235 00:54:26,560 --> 00:54:30,600 And so I'm going to import render template, which is a function. 1236 00:54:30,600 --> 00:54:32,350 And rather than returning hello world, I'm 1237 00:54:32,350 --> 00:54:36,940 going to return render template index dot HTML. 1238 00:54:36,940 --> 00:54:39,310 And now on the desktop, I'm going to make a directory, 1239 00:54:39,310 --> 00:54:41,380 a new folder called templates. 1240 00:54:41,380 --> 00:54:45,330 And inside of the templates directory, I'm 1241 00:54:45,330 --> 00:54:49,050 going to add a new file called index dot HTML. 1242 00:54:49,050 --> 00:54:52,400 And in index dot HTML we're going to say HTML-- 1243 00:54:52,400 --> 00:54:55,210 1244 00:54:55,210 --> 00:55:01,970 you can have any arbitrary HTML page. 1245 00:55:01,970 --> 00:55:04,960 So now I type Flask run. 1246 00:55:04,960 --> 00:55:06,330 I go to the route. 1247 00:55:06,330 --> 00:55:07,664 And I get welcome to my website. 1248 00:55:07,664 --> 00:55:09,663 Again, I went through that a little bit quickly. 1249 00:55:09,663 --> 00:55:12,090 But basically what I've done here is I have in application 1250 00:55:12,090 --> 00:55:15,870 dot pi render template, rendering some template to the user. 1251 00:55:15,870 --> 00:55:19,740 This file, index dot HTML is located inside 1252 00:55:19,740 --> 00:55:22,410 of a templates directory that's in the same folder 1253 00:55:22,410 --> 00:55:26,160 as application dot by so I have index dot HTML, which is a template 1254 00:55:26,160 --> 00:55:27,440 that I'm loading. 1255 00:55:27,440 --> 00:55:29,520 And the nice thing about these templates is 1256 00:55:29,520 --> 00:55:35,790 that I can now add arbitrary logic and variables to these templates, whereby 1257 00:55:35,790 --> 00:55:40,020 I can say if I go to slash string name, and I 1258 00:55:40,020 --> 00:55:43,230 want to say hello to someone's name, then 1259 00:55:43,230 --> 00:55:47,660 I can render index dot HTML passing in the variable name. 1260 00:55:47,660 --> 00:55:50,699 And I want to set that equal to whatever name is, 1261 00:55:50,699 --> 00:55:52,490 but I probably want to capitalize it first. 1262 00:55:52,490 --> 00:55:55,370 So name dot capitalize. 1263 00:55:55,370 --> 00:56:00,970 And then in index dot HTML, and I'll go ahead and show both side by side, 1264 00:56:00,970 --> 00:56:08,997 welcome to my website comma, and then in two curly braces I'm going to say name. 1265 00:56:08,997 --> 00:56:09,830 And this is indexed. 1266 00:56:09,830 --> 00:56:12,996 You probably remember from CS50 this is a special templating language called 1267 00:56:12,996 --> 00:56:17,530 Ginga that just makes it easy to be able to template languages in order 1268 00:56:17,530 --> 00:56:21,160 to generate HTML files that are dynamic, that aren't the same every time you 1269 00:56:21,160 --> 00:56:23,440 open the page, but that actually change depending 1270 00:56:23,440 --> 00:56:27,380 on the value of variables, for example. 1271 00:56:27,380 --> 00:56:29,440 So now if I were to run this application, 1272 00:56:29,440 --> 00:56:31,870 go to slash Josh, for example. 1273 00:56:31,870 --> 00:56:35,860 Then I get welcome to my website comma Josh, where Josh was capitalized. 1274 00:56:35,860 --> 00:56:39,250 Reason being, in application dot pi, I want to slash Josh. 1275 00:56:39,250 --> 00:56:42,360 So Josh is the value of this variable called name. 1276 00:56:42,360 --> 00:56:47,440 I'm capitalizing that name, passing it into the template as something also 1277 00:56:47,440 --> 00:56:50,240 called name-- but it could have been called something different-- 1278 00:56:50,240 --> 00:56:54,220 and then in the template I'm saying welcome to my website comma 1279 00:56:54,220 --> 00:56:58,074 and then plugging in the name there. 1280 00:56:58,074 --> 00:56:59,240 Questions about any of that? 1281 00:56:59,240 --> 00:57:03,780 1282 00:57:03,780 --> 00:57:04,750 OK. 1283 00:57:04,750 --> 00:57:08,825 In that case what I thought we'd do is try adding some conditions 1284 00:57:08,825 --> 00:57:09,700 to this web page now. 1285 00:57:09,700 --> 00:57:13,510 So one of my personal favorite stupid websites 1286 00:57:13,510 --> 00:57:16,020 is a website called Is It Christmas dot com. 1287 00:57:16,020 --> 00:57:18,630 Anyone familiar with it? 1288 00:57:18,630 --> 00:57:19,942 A couple of people, maybe. 1289 00:57:19,942 --> 00:57:22,900 Basically, it's a website that tells you whether or not it's Christmas. 1290 00:57:22,900 --> 00:57:26,490 You go to is it Christmas dot com press Return. 1291 00:57:26,490 --> 00:57:29,830 And this is the page. 1292 00:57:29,830 --> 00:57:32,260 So very simple website. 1293 00:57:32,260 --> 00:57:33,940 It just says no. 1294 00:57:33,940 --> 00:57:37,150 On Christmas it says yes. 1295 00:57:37,150 --> 00:57:39,820 And what I thought we'd do is create a website called is it 1296 00:57:39,820 --> 00:57:43,510 New Year's just to get it the idea OK, how can we actually implement 1297 00:57:43,510 --> 00:57:46,060 this sort of logic in Python and Flask in order 1298 00:57:46,060 --> 00:57:49,770 to generate something somewhat interesting. 1299 00:57:49,770 --> 00:57:54,814 And so in Python, there is a module called date time, which 1300 00:57:54,814 --> 00:57:56,230 we're going to end up being using. 1301 00:57:56,230 --> 00:57:58,480 And I'll important date time so that we can use it. 1302 00:57:58,480 --> 00:58:03,040 And in Python, if I do something like date time dot date time dot now, 1303 00:58:03,040 --> 00:58:06,460 that's going to give me a value that represents like, the current moment, 1304 00:58:06,460 --> 00:58:09,990 January 20, 2019 that 11: 06 AM, and some number of seconds 1305 00:58:09,990 --> 00:58:10,960 and milliseconds. 1306 00:58:10,960 --> 00:58:13,480 It's going to give me all that information. 1307 00:58:13,480 --> 00:58:18,430 If I do date time dot date time dot now dot month, I get just one. 1308 00:58:18,430 --> 00:58:21,190 That is the month of the current time stamp. 1309 00:58:21,190 --> 00:58:25,900 And I do dot day, and I get 20, which is the current day of today. 1310 00:58:25,900 --> 00:58:27,940 And so I can use date time dot date time dot now 1311 00:58:27,940 --> 00:58:30,340 to be able to answer these sorts of questions. 1312 00:58:30,340 --> 00:58:36,920 So in application dot pi now, let's go ahead and say-- 1313 00:58:36,920 --> 00:58:40,240 well, let me first at the top of the file import date time, 1314 00:58:40,240 --> 00:58:42,100 so we can use the daytime module. 1315 00:58:42,100 --> 00:58:45,760 And we'll say now equals date time dot date time dot now. 1316 00:58:45,760 --> 00:58:49,570 And I'll create a new variable called is New Year's. 1317 00:58:49,570 --> 00:58:56,920 And is New Year's is going to be set to now dot month equals one and now dot 1318 00:58:56,920 --> 00:59:01,790 day equals one, meaning if both the month of what the time stamp is right 1319 00:59:01,790 --> 00:59:06,620 now is January is January for one, and now dot day is also one, 1320 00:59:06,620 --> 00:59:09,790 then it is New Year's. 1321 00:59:09,790 --> 00:59:12,970 And then I'm going to load index dot HTML passing in 1322 00:59:12,970 --> 00:59:16,450 is New Year's into the template. 1323 00:59:16,450 --> 00:59:18,355 I don't need string name anymore. 1324 00:59:18,355 --> 00:59:21,030 So I can get rid of that variable. 1325 00:59:21,030 --> 00:59:23,570 So I just have this is New Year's variable now. 1326 00:59:23,570 --> 00:59:28,280 And now inside of index.HTML I can add some logic. 1327 00:59:28,280 --> 00:59:34,440 I can say if is New Year's, then-- 1328 00:59:34,440 --> 00:59:43,000 I'll do H1-- yes else H1 no end if. 1329 00:59:43,000 --> 00:59:46,290 So this right here is the Ginga syntax for creating a condition. 1330 00:59:46,290 --> 00:59:50,910 Use these curly braces and percent symbols say if something, and then 1331 00:59:50,910 --> 00:59:55,050 any arbitrary HTML inside of that, else some other condition. 1332 00:59:55,050 --> 00:59:57,491 And then end if to say that's the end of the if statement. 1333 00:59:57,491 --> 00:59:59,490 So we've checked whether or not it's a new year, 1334 00:59:59,490 --> 01:00:01,323 and depending on whether it is or not, we're 1335 01:00:01,323 --> 01:00:03,290 going to get some different output. 1336 01:00:03,290 --> 01:00:07,590 And so I run this web application now, Flask run. 1337 01:00:07,590 --> 01:00:12,510 I go to the web page, no particular route, press Return. 1338 01:00:12,510 --> 01:00:13,680 And OK, it says no. 1339 01:00:13,680 --> 01:00:15,060 It is not New Year's Day today. 1340 01:00:15,060 --> 01:00:18,840 We could cheat a little bit and in application dot pi just to test it, 1341 01:00:18,840 --> 01:00:22,320 we can say is now a day equal to 20, which is today? 1342 01:00:22,320 --> 01:00:24,690 And if I try refreshing this page, then OK. 1343 01:00:24,690 --> 01:00:26,420 Yes, today is January 20. 1344 01:00:26,420 --> 01:00:28,830 It's going to show me that as well. 1345 01:00:28,830 --> 01:00:31,050 So this sort of logic of logic we can use 1346 01:00:31,050 --> 01:00:33,600 to be able to create conditions inside of our application 1347 01:00:33,600 --> 01:00:38,210 to do different things, depending on what's happening in the program. 1348 01:00:38,210 --> 01:00:39,590 Questions about that so far? 1349 01:00:39,590 --> 01:00:44,450 1350 01:00:44,450 --> 01:00:44,950 Yeah? 1351 01:00:44,950 --> 01:00:47,530 AUDIENCE: [INAUDIBLE] 1352 01:00:47,530 --> 01:00:48,530 BRIAN YU: Good question. 1353 01:00:48,530 --> 01:00:50,090 So what language is the Ginga code? 1354 01:00:50,090 --> 01:00:51,923 The Ginga code is actually its own language. 1355 01:00:51,923 --> 01:00:53,570 Ginga is a templating language. 1356 01:00:53,570 --> 01:00:56,580 It's a language that draws a lot of inspiration from Python though. 1357 01:00:56,580 --> 01:00:58,700 So it's got a lot in common with Python. 1358 01:00:58,700 --> 01:01:02,990 So a lot of the similar ideas of if and [INAUDIBLE] if and else from Python. 1359 01:01:02,990 --> 01:01:05,750 Those keywords are also going to be present in Ginga. 1360 01:01:05,750 --> 01:01:08,240 So you can do a lot of those same things in Ginga. 1361 01:01:08,240 --> 01:01:10,680 Syntax. 1362 01:01:10,680 --> 01:01:11,440 So all right. 1363 01:01:11,440 --> 01:01:15,270 What I thought we'd do now is together begin working 1364 01:01:15,270 --> 01:01:18,150 on what's going to be today's project. 1365 01:01:18,150 --> 01:01:20,340 And we'll work on this together for a little bit, 1366 01:01:20,340 --> 01:01:22,290 and then I'll set you free to work on a couple of features. 1367 01:01:22,290 --> 01:01:23,320 Then we'll do our lunch break. 1368 01:01:23,320 --> 01:01:25,403 We'll come back in the afternoon for a little more 1369 01:01:25,403 --> 01:01:27,450 on Flask and artificial intelligence. 1370 01:01:27,450 --> 01:01:29,520 And then we'll continue working on that project. 1371 01:01:29,520 --> 01:01:33,060 And so the project that we're going to be working on today 1372 01:01:33,060 --> 01:01:37,710 is we're going to try and implement a game of tic-tac-toe online. 1373 01:01:37,710 --> 01:01:40,800 And so here is what the finished application 1374 01:01:40,800 --> 01:01:42,835 is going to look like potentially. 1375 01:01:42,835 --> 01:01:44,710 Uh-oh, import error. 1376 01:01:44,710 --> 01:01:46,390 No module named Flask session. 1377 01:01:46,390 --> 01:01:48,930 Let me-- if you ever get an import error where 1378 01:01:48,930 --> 01:01:52,870 there's no module with a particular name, you can PIP3 install it. 1379 01:01:52,870 --> 01:01:55,840 I'll go ahead and install that now. 1380 01:01:55,840 --> 01:01:57,100 Flask run. 1381 01:01:57,100 --> 01:01:58,480 Great. 1382 01:01:58,480 --> 01:02:00,087 Run that application. 1383 01:02:00,087 --> 01:02:02,170 Here's what the application is going to look like. 1384 01:02:02,170 --> 01:02:04,545 We're just going to have a grid, where we can make moves. 1385 01:02:04,545 --> 01:02:06,180 This grid is just an HTML table. 1386 01:02:06,180 --> 01:02:07,570 And OK, it's X's turn first. 1387 01:02:07,570 --> 01:02:09,070 X is going to play somewhere. 1388 01:02:09,070 --> 01:02:11,250 O can play somewhere, X can play somewhere. 1389 01:02:11,250 --> 01:02:13,190 O can not play very well. 1390 01:02:13,190 --> 01:02:17,500 And if X plays here, then it says OK, winner of the game 1391 01:02:17,500 --> 01:02:19,527 is X. It's a fairly straightforward game. 1392 01:02:19,527 --> 01:02:20,860 You can add additional features. 1393 01:02:20,860 --> 01:02:24,070 We'll add a button to reset the game too, which I'll have you implement. 1394 01:02:24,070 --> 01:02:28,900 Play x there, O, X. Maybe o is not going to be very smart again. 1395 01:02:28,900 --> 01:02:32,590 And later this afternoon when we talk about artificial intelligence 1396 01:02:32,590 --> 01:02:35,380 and algorithms like min and max for being able to play games, 1397 01:02:35,380 --> 01:02:37,600 we'll have you, if you'd like to, try a challenge, 1398 01:02:37,600 --> 01:02:40,810 try to implement an artificial intelligence to play this game so 1399 01:02:40,810 --> 01:02:43,420 that you can choose let computer make move. 1400 01:02:43,420 --> 01:02:45,379 Click on that button and that's going to result 1401 01:02:45,379 --> 01:02:47,169 in X playing in a particular position. it's 1402 01:02:47,169 --> 01:02:49,900 going to say winner is X. We're not going to get there just yet, 1403 01:02:49,900 --> 01:02:51,760 but we'll explain the algorithm later this afternoon 1404 01:02:51,760 --> 01:02:53,110 so that if you'd like to try it. 1405 01:02:53,110 --> 01:02:55,270 It's something that you can try but all right. 1406 01:02:55,270 --> 01:02:57,370 Let's actually just start simple and start 1407 01:02:57,370 --> 01:03:01,220 trying to create this web application. 1408 01:03:01,220 --> 01:03:04,244 So in a new folder, I'm going to call it tic-tac-toe. 1409 01:03:04,244 --> 01:03:07,170 1410 01:03:07,170 --> 01:03:12,870 I'm going to create a new file called application dot pi. 1411 01:03:12,870 --> 01:03:16,250 1412 01:03:16,250 --> 01:03:23,470 And we're going to say from Flask import flask. 1413 01:03:23,470 --> 01:03:29,209 1414 01:03:29,209 --> 01:03:32,000 In order to give everyone a different game, what we're going to use 1415 01:03:32,000 --> 01:03:33,416 is something called Flask session. 1416 01:03:33,416 --> 01:03:36,590 1417 01:03:36,590 --> 01:03:41,650 You used Flask session when you were doing CS50 finance. 1418 01:03:41,650 --> 01:03:43,400 And you wanted to use CS50 finance to keep 1419 01:03:43,400 --> 01:03:45,830 track of which is the current user that is logged in, 1420 01:03:45,830 --> 01:03:48,140 so that different people logged in and could see their own different stock 1421 01:03:48,140 --> 01:03:49,070 portfolios. 1422 01:03:49,070 --> 01:03:50,990 In this case, we're going to use Flask session 1423 01:03:50,990 --> 01:03:53,210 to do the same idea, where instead of just giving people 1424 01:03:53,210 --> 01:03:55,040 a different account, anyone who's logged in 1425 01:03:55,040 --> 01:03:57,560 is going to be able to play their own game online. 1426 01:03:57,560 --> 01:03:59,810 So the session inside of the session we're 1427 01:03:59,810 --> 01:04:02,740 going to store details about the current game. 1428 01:04:02,740 --> 01:04:06,280 So we're going to say app equals Flask name. 1429 01:04:06,280 --> 01:04:08,030 Then we're going to have a couple of lines 1430 01:04:08,030 --> 01:04:10,061 that you might recall from CS50 finance. 1431 01:04:10,061 --> 01:04:11,810 So you don't need to worry too much about, 1432 01:04:11,810 --> 01:04:14,270 but they're just some configuration settings. 1433 01:04:14,270 --> 01:04:19,040 We're going to say config session file der equals make D temp. 1434 01:04:19,040 --> 01:04:20,810 Don't worry too much about these lines. 1435 01:04:20,810 --> 01:04:23,226 I'll post some source code examples that you can copy this 1436 01:04:23,226 --> 01:04:26,750 from so you don't need to feel like you need to copy them directly right now. 1437 01:04:26,750 --> 01:04:32,150 I'll need to import from temp file import make D temp. 1438 01:04:32,150 --> 01:04:34,250 Basically, if you're curious what this is doing is 1439 01:04:34,250 --> 01:04:36,950 we need some place to actually store the session data. 1440 01:04:36,950 --> 01:04:39,794 The session is data that our application needs to source somewhere. 1441 01:04:39,794 --> 01:04:41,960 And we're just going to create a temporary directory 1442 01:04:41,960 --> 01:04:45,560 in which to store all of that session information. 1443 01:04:45,560 --> 01:04:48,122 We need to say should the session be permanent? 1444 01:04:48,122 --> 01:04:50,330 And we're going to say no, it shouldn't be permanent. 1445 01:04:50,330 --> 01:04:52,250 After some time it's going to expire. 1446 01:04:52,250 --> 01:04:56,060 There are fancier ways of trying to set exactly what that time is going to be. 1447 01:04:56,060 --> 01:04:59,470 And then the session type, what type of session is this going to be? 1448 01:04:59,470 --> 01:05:01,410 I'm going to say file system. 1449 01:05:01,410 --> 01:05:04,439 In other words, there are different ways of storing session information. 1450 01:05:04,439 --> 01:05:06,980 I'm going to store all the session information just in files. 1451 01:05:06,980 --> 01:05:09,800 You could store them in databases and cookies and other ways. 1452 01:05:09,800 --> 01:05:12,800 Again, I wouldn't worry about any of these first couple of lines 1453 01:05:12,800 --> 01:05:13,550 that I've written. 1454 01:05:13,550 --> 01:05:15,770 These are just configuration to get the application 1455 01:05:15,770 --> 01:05:18,140 to work the way we want it to. 1456 01:05:18,140 --> 01:05:20,580 Here's where the interesting stuff starts to happen. 1457 01:05:20,580 --> 01:05:25,310 So if I go to the slash route, we'll call this the index function. 1458 01:05:25,310 --> 01:05:29,249 And what I want to do is get the board from the session. 1459 01:05:29,249 --> 01:05:31,040 Like, what I probably want to do eventually 1460 01:05:31,040 --> 01:05:35,660 is store the board, the tic-tac-toe board, inside of session square bracket 1461 01:05:35,660 --> 01:05:38,060 board. 1462 01:05:38,060 --> 01:05:40,790 And what might this board look like? 1463 01:05:40,790 --> 01:05:42,920 Like, what sort of data structure do you envision 1464 01:05:42,920 --> 01:05:46,460 that we could use to store this board? 1465 01:05:46,460 --> 01:05:46,960 Thoughts? 1466 01:05:46,960 --> 01:05:49,820 1467 01:05:49,820 --> 01:05:50,320 Yeah? 1468 01:05:50,320 --> 01:05:51,475 AUDIENCE: [INAUDIBLE] 1469 01:05:51,475 --> 01:05:52,100 BRIAN YU: Yeah. 1470 01:05:52,100 --> 01:05:53,040 A list of lists. 1471 01:05:53,040 --> 01:05:56,190 You might imagine that we have one list for each row. 1472 01:05:56,190 --> 01:06:00,030 And each row is just going to be a list of three things, either x or zero, 1473 01:06:00,030 --> 01:06:02,340 or some value to represent nothing is here yet, 1474 01:06:02,340 --> 01:06:04,510 which might just be the none value. 1475 01:06:04,510 --> 01:06:07,450 And so the logic I'm going to start you off with 1476 01:06:07,450 --> 01:06:13,120 is say if a board not in session. 1477 01:06:13,120 --> 01:06:17,880 In other words, if there is not already a board inside of the session, 1478 01:06:17,880 --> 01:06:20,320 then I better create the new board. 1479 01:06:20,320 --> 01:06:24,032 We'll say section board is equal to-- 1480 01:06:24,032 --> 01:06:26,240 and right now you need to create an empty game board. 1481 01:06:26,240 --> 01:06:28,860 And then someone suggested maybe this can be a list of lists. 1482 01:06:28,860 --> 01:06:30,660 The first row has nothing in it. 1483 01:06:30,660 --> 01:06:32,970 So we'll just say none, none, none. 1484 01:06:32,970 --> 01:06:36,090 The second row also has nothing in it, none, none, none. 1485 01:06:36,090 --> 01:06:40,440 The third row also has nothing in it, none, none, none. 1486 01:06:40,440 --> 01:06:43,724 So we've created the board inside of the session. 1487 01:06:43,724 --> 01:06:46,890 What other information do we need to keep track of with regards to the game? 1488 01:06:46,890 --> 01:06:50,230 1489 01:06:50,230 --> 01:06:51,010 Whose turn it is. 1490 01:06:51,010 --> 01:06:51,250 Great. 1491 01:06:51,250 --> 01:06:53,750 And we could probably calculate that based on the board. 1492 01:06:53,750 --> 01:06:55,900 But for simplicity's sake, let's go ahead and store that in the session 1493 01:06:55,900 --> 01:06:56,530 too. 1494 01:06:56,530 --> 01:06:58,360 I'll say session square bracket turn. 1495 01:06:58,360 --> 01:06:59,950 We'll have X go first. 1496 01:06:59,950 --> 01:07:03,100 So the current turn is just X. They're the player who 1497 01:07:03,100 --> 01:07:05,500 is going to be playing first. 1498 01:07:05,500 --> 01:07:10,910 And now let me go ahead and just render a return, render a template. 1499 01:07:10,910 --> 01:07:12,940 We'll call it game dot HTML. 1500 01:07:12,940 --> 01:07:16,870 And we'll pass in game is going to be session board, because I 1501 01:07:16,870 --> 01:07:19,995 need have access to the board inside of my HTML template. 1502 01:07:19,995 --> 01:07:22,120 And I also need to have access to whose turn it is. 1503 01:07:22,120 --> 01:07:24,550 So turn is going to be session turn. 1504 01:07:24,550 --> 01:07:27,400 So inside of game dot HTML I will have access 1505 01:07:27,400 --> 01:07:30,940 to a variable called game, which is this list of all the current state 1506 01:07:30,940 --> 01:07:34,150 of the board, and also a variable called turn, that 1507 01:07:34,150 --> 01:07:37,360 represents whose turn it is right now. 1508 01:07:37,360 --> 01:07:43,530 And so I'll go ahead and create a new folder called templates, 1509 01:07:43,530 --> 01:07:48,030 inside of which I'll create a new file called game dot HTML. 1510 01:07:48,030 --> 01:07:53,180 And OK, inside of game dot HTML I'm going to include some code. 1511 01:07:53,180 --> 01:07:59,720 Dot type HTML, HTML head title is going to be tic-tac-toe. 1512 01:07:59,720 --> 01:08:04,530 And inside the body of this application I'm just going to create a table. 1513 01:08:04,530 --> 01:08:05,870 So a table. 1514 01:08:05,870 --> 01:08:08,540 And what I'd like to do is create three rows, 1515 01:08:08,540 --> 01:08:11,150 one for each row of the game board. 1516 01:08:11,150 --> 01:08:12,740 And so I'm going to do a Ginga loop. 1517 01:08:12,740 --> 01:08:15,614 And a loop in Ginga very similar to what a loop in Python looks like. 1518 01:08:15,614 --> 01:08:18,080 I'm going to just say for I in range three. 1519 01:08:18,080 --> 01:08:23,740 I want to do a loop that's going to run three times, zero, one, two. 1520 01:08:23,740 --> 01:08:24,740 What do I need three of? 1521 01:08:24,740 --> 01:08:26,420 I need three rows. 1522 01:08:26,420 --> 01:08:30,080 TR is the HTML tag for creating an HTML row. 1523 01:08:30,080 --> 01:08:32,840 So I'm going to create a row using TR. 1524 01:08:32,840 --> 01:08:35,121 And inside of that row what do I need? 1525 01:08:35,121 --> 01:08:38,390 1526 01:08:38,390 --> 01:08:42,220 What do I need in each row of the tic-tac-toe game board? 1527 01:08:42,220 --> 01:08:43,529 A TD. 1528 01:08:43,529 --> 01:08:46,340 TD stands for table data or a table cell. 1529 01:08:46,340 --> 01:08:48,779 And how many table cells do I need? 1530 01:08:48,779 --> 01:08:49,290 Three. 1531 01:08:49,290 --> 01:08:49,439 Great. 1532 01:08:49,439 --> 01:08:51,080 It's a three by three game board. 1533 01:08:51,080 --> 01:08:56,700 So I'm going to have another loop in here for J in range three and four. 1534 01:08:56,700 --> 01:08:59,540 1535 01:08:59,540 --> 01:09:04,399 And so inside of each one of these is going to be a TD, a table data cell. 1536 01:09:04,399 --> 01:09:09,539 And for now, I'm just going to say like, this is a cell, just so I can test this 1537 01:09:09,539 --> 01:09:11,080 out, see whether or not it's working. 1538 01:09:11,080 --> 01:09:13,740 Oftentimes, a good strategy before you try to the entire thing 1539 01:09:13,740 --> 01:09:15,699 is build a very small piece of it, just a game 1540 01:09:15,699 --> 01:09:18,240 board that is three by three each filled with this is a cell, 1541 01:09:18,240 --> 01:09:19,420 and see if that works. 1542 01:09:19,420 --> 01:09:21,160 And then go from there. 1543 01:09:21,160 --> 01:09:24,399 So I'll try this, run Flask run. 1544 01:09:24,399 --> 01:09:26,939 Go ahead and start up the server. 1545 01:09:26,939 --> 01:09:29,160 Named session is not defined. 1546 01:09:29,160 --> 01:09:31,227 OK, I think I missed a line somewhere. 1547 01:09:31,227 --> 01:09:34,090 1548 01:09:34,090 --> 01:09:35,620 Yes, actually missed a couple lines. 1549 01:09:35,620 --> 01:09:38,080 First thing I need do is from Flask I need to import 1550 01:09:38,080 --> 01:09:42,130 both render template and session. 1551 01:09:42,130 --> 01:09:48,100 And also to enable sessions, I also need to say session app. 1552 01:09:48,100 --> 01:09:50,314 So I added some additional imports that I needed. 1553 01:09:50,314 --> 01:09:51,939 I want to be able to render a template. 1554 01:09:51,939 --> 01:09:54,010 I want to be able to access the session. 1555 01:09:54,010 --> 01:09:58,180 And to enable Flask session, I have to say create sessions out 1556 01:09:58,180 --> 01:09:59,254 of this web application. 1557 01:09:59,254 --> 01:10:01,420 Again, no need to worry about the specifics of that. 1558 01:10:01,420 --> 01:10:05,890 These are lines you can very frequently copy anytime you need to use them. 1559 01:10:05,890 --> 01:10:09,280 So let's try and refresh that, run it again. 1560 01:10:09,280 --> 01:10:10,000 OK. 1561 01:10:10,000 --> 01:10:14,497 I have the basics of what is eventually going to be a game board. 1562 01:10:14,497 --> 01:10:17,080 Doesn't look much like a tic-tac-toe game board at the moment, 1563 01:10:17,080 --> 01:10:17,720 but that's OK. 1564 01:10:17,720 --> 01:10:21,580 We can add some additional logic here to be able to help us out here. 1565 01:10:21,580 --> 01:10:24,220 And the logic is mostly going to come from styling code. 1566 01:10:24,220 --> 01:10:26,260 So inside the style section of our website 1567 01:10:26,260 --> 01:10:28,690 let's add some CSS that's going to make this actually look 1568 01:10:28,690 --> 01:10:30,520 like a tic-tac-toe board. 1569 01:10:30,520 --> 01:10:35,410 So for tables and table data cells, I wanted 1570 01:10:35,410 --> 01:10:40,367 to have a border that is a one pixel solid block border. 1571 01:10:40,367 --> 01:10:43,450 This is basically going to say around the table and around any data cells, 1572 01:10:43,450 --> 01:10:47,390 go in and create a one pixel border around it. 1573 01:10:47,390 --> 01:10:48,942 And so what's that going to do? 1574 01:10:48,942 --> 01:10:51,150 It's going to give me something that looks like this. 1575 01:10:51,150 --> 01:10:51,650 All right. 1576 01:10:51,650 --> 01:10:55,090 That looks a little bit more like the game board that I expect. 1577 01:10:55,090 --> 01:10:57,090 And actually, I wonder if I can get rid of table 1578 01:10:57,090 --> 01:10:59,760 and just do round table data cells. 1579 01:10:59,760 --> 01:11:01,890 All right, if I just go around table data cells, 1580 01:11:01,890 --> 01:11:05,310 then I'll get something that looks like this. 1581 01:11:05,310 --> 01:11:09,520 But what I can do is to make this look a little better, 1582 01:11:09,520 --> 01:11:11,340 I'm going to add styling to the table. 1583 01:11:11,340 --> 01:11:14,580 Say border collapse collapse. 1584 01:11:14,580 --> 01:11:15,810 And let's see if that works. 1585 01:11:15,810 --> 01:11:16,530 Yes, great. 1586 01:11:16,530 --> 01:11:19,380 So border collapse is just a special CSS property 1587 01:11:19,380 --> 01:11:21,160 you can add to a table that says if there 1588 01:11:21,160 --> 01:11:24,660 are two borders next to each other, collapse them down into one. 1589 01:11:24,660 --> 01:11:27,540 So without it before, the game board look something 1590 01:11:27,540 --> 01:11:29,950 like this with all the lines sort of next to each other, 1591 01:11:29,950 --> 01:11:31,230 but multiple of them. 1592 01:11:31,230 --> 01:11:34,570 If I add in this border collapse collapse CSS property, 1593 01:11:34,570 --> 01:11:35,790 refresh it again. 1594 01:11:35,790 --> 01:11:38,190 All the lines sort of come together, so we actually 1595 01:11:38,190 --> 01:11:43,290 get something that looks a little bit more like a game board. 1596 01:11:43,290 --> 01:11:45,030 Questions about that CSS code so far? 1597 01:11:45,030 --> 01:11:47,720 1598 01:11:47,720 --> 01:11:48,830 All right. 1599 01:11:48,830 --> 01:11:51,620 So now what I want to do is I'd like to make these cells square. 1600 01:11:51,620 --> 01:11:54,680 So for each of these table data cells, I'll give them a width 1601 01:11:54,680 --> 01:11:56,810 and say 150 pixels. 1602 01:11:56,810 --> 01:11:59,390 I'll give them a height, also 150 pixels. 1603 01:11:59,390 --> 01:12:03,720 And I'll give it a font size of 30 pixels. 1604 01:12:03,720 --> 01:12:08,170 And we'll center it, text align center. 1605 01:12:08,170 --> 01:12:10,940 So width and height I'm setting to the same value, 150 pixels. 1606 01:12:10,940 --> 01:12:12,955 So I get some big squares for the game. 1607 01:12:12,955 --> 01:12:15,830 I'm setting the font size of what size the text inside the game board 1608 01:12:15,830 --> 01:12:16,850 should be. 1609 01:12:16,850 --> 01:12:19,945 30 pixels is what the size of like, the X and the O is going to be. 1610 01:12:19,945 --> 01:12:22,820 And then I'm sending that text, because I want the X's and O's always 1611 01:12:22,820 --> 01:12:26,210 to be centered inside the game board. 1612 01:12:26,210 --> 01:12:30,730 So I'll refresh this, and I get something far too big. 1613 01:12:30,730 --> 01:12:32,382 Something that looks like this. 1614 01:12:32,382 --> 01:12:34,840 Now, this actually looks like a game board, but in each one 1615 01:12:34,840 --> 01:12:36,845 I've just said this is a set. 1616 01:12:36,845 --> 01:12:39,220 So now I'd like to show something a little bit different, 1617 01:12:39,220 --> 01:12:41,345 as opposed to this is the cell in every single one. 1618 01:12:41,345 --> 01:12:43,180 But before I move on, question so far? 1619 01:12:43,180 --> 01:12:47,721 1620 01:12:47,721 --> 01:12:48,220 All right. 1621 01:12:48,220 --> 01:12:51,160 1622 01:12:51,160 --> 01:12:54,520 Let's go ahead and try now, instead of just 1623 01:12:54,520 --> 01:12:58,690 saying this is a cell, what we can do is we can plug in the value of variables 1624 01:12:58,690 --> 01:13:00,740 here, variables like I and J, for instance. 1625 01:13:00,740 --> 01:13:03,580 So I can say double Curly Brace I comma double 1626 01:13:03,580 --> 01:13:07,360 Curly Brace J to print out what the values of I and J 1627 01:13:07,360 --> 01:13:09,709 are in any particular case. 1628 01:13:09,709 --> 01:13:12,750 And so I'll refresh this page to show you what that's going to look like. 1629 01:13:12,750 --> 01:13:13,458 And so all right. 1630 01:13:13,458 --> 01:13:16,040 Now I've printed out the coordinates of each 1631 01:13:16,040 --> 01:13:17,790 of the cells of my tic-tac-toe game board. 1632 01:13:17,790 --> 01:13:20,090 In the upper left I have rows zero column zero. 1633 01:13:20,090 --> 01:13:22,510 Next to that is row zero column one. 1634 01:13:22,510 --> 01:13:26,050 After that I have row zero column two. 1635 01:13:26,050 --> 01:13:29,320 Then I have row one column zero, one, and two, and then row two 1636 01:13:29,320 --> 01:13:30,610 down there on the bottom. 1637 01:13:30,610 --> 01:13:33,100 And so I have all these cells of the game board. 1638 01:13:33,100 --> 01:13:36,040 And now what I'd like to do, instead of just printing out the cells, 1639 01:13:36,040 --> 01:13:43,260 let's print out game I J. In other words, 1640 01:13:43,260 --> 01:13:48,995 print out whatever is stored in the game board at row I and column J. 1641 01:13:48,995 --> 01:13:51,120 And so when I refresh this, what am I going to see? 1642 01:13:51,120 --> 01:13:51,620 Any guesses? 1643 01:13:51,620 --> 01:13:56,440 1644 01:13:56,440 --> 01:13:59,530 This is what I get, A board full of nones, 1645 01:13:59,530 --> 01:14:04,000 because inside of my array, this game board array, session Square Bracket 1646 01:14:04,000 --> 01:14:07,630 board, I just filled it with a whole bunch of nothing, none values. 1647 01:14:07,630 --> 01:14:12,120 If I were to change one of them and make it X instead, refresh that. 1648 01:14:12,120 --> 01:14:16,140 OK, now it's X, because I'm able to change the board. 1649 01:14:16,140 --> 01:14:18,130 But I'll leave it if none for now. 1650 01:14:18,130 --> 01:14:21,061 What I'd like to do is not show the word none if nothing is there. 1651 01:14:21,061 --> 01:14:23,560 If nothing is there, I'd like to show like, a link that says 1652 01:14:23,560 --> 01:14:26,460 like play a move here. 1653 01:14:26,460 --> 01:14:27,960 So let me go back. 1654 01:14:27,960 --> 01:14:29,420 And so what's the logic here? 1655 01:14:29,420 --> 01:14:31,320 I want to show the move if there is a move. 1656 01:14:31,320 --> 01:14:32,510 But if there's no move, then I want to show 1657 01:14:32,510 --> 01:14:34,520 a link that lets you play a move there. 1658 01:14:34,520 --> 01:14:36,236 What sort of structure do I need? 1659 01:14:36,236 --> 01:14:38,910 1660 01:14:38,910 --> 01:14:39,410 Yeah? 1661 01:14:39,410 --> 01:14:40,400 AUDIENCE: [INAUDIBLE]. 1662 01:14:40,400 --> 01:14:42,608 BRIAN YU: Yeah, some sort of conditional, somewhere I 1663 01:14:42,608 --> 01:14:46,520 can say if game I J, in other words, if there is something 1664 01:14:46,520 --> 01:14:49,640 in this spot in the game, then go ahead and print out 1665 01:14:49,640 --> 01:14:55,980 whatever it is there, else [INAUDIBLE] if we'll 1666 01:14:55,980 --> 01:14:58,134 go ahead and add a link, a HREF. 1667 01:14:58,134 --> 01:14:59,800 Right now it's not going to go anywhere. 1668 01:14:59,800 --> 01:15:03,360 I'll just have it go to pound symbol, which just takes you to the same page 1669 01:15:03,360 --> 01:15:05,790 and say play. 1670 01:15:05,790 --> 01:15:07,110 And then whose turn is it? 1671 01:15:07,110 --> 01:15:10,140 The current turn is stored in a variable called turn. 1672 01:15:10,140 --> 01:15:12,750 So I can print it out at this point in the game 1673 01:15:12,750 --> 01:15:16,830 by saying play Curly Brace Curly Brace turn here. 1674 01:15:16,830 --> 01:15:19,430 1675 01:15:19,430 --> 01:15:20,530 All right. 1676 01:15:20,530 --> 01:15:21,130 Play X here. 1677 01:15:21,130 --> 01:15:22,180 Play X here. 1678 01:15:22,180 --> 01:15:24,850 And now I have that ability. 1679 01:15:24,850 --> 01:15:28,090 These links are a little bit big, so I might want to add some styling code. 1680 01:15:28,090 --> 01:15:29,650 Feel free to mess with the styling on your own. 1681 01:15:29,650 --> 01:15:30,858 But I want to say, all right. 1682 01:15:30,858 --> 01:15:34,210 For all the links that are children of table data cells, 1683 01:15:34,210 --> 01:15:37,970 that font size should just be 18 point font, for instance. 1684 01:15:37,970 --> 01:15:41,710 So those links now are just going to be 18 point font, instead of 30 point 1685 01:15:41,710 --> 01:15:43,420 font. 1686 01:15:43,420 --> 01:15:44,241 Refresh that. 1687 01:15:44,241 --> 01:15:44,740 OK. 1688 01:15:44,740 --> 01:15:46,037 This looks a little bit nicer. 1689 01:15:46,037 --> 01:15:48,370 Of course, these buttons don't actually do anything yet. 1690 01:15:48,370 --> 01:15:50,380 I say play X here, nothing happens. 1691 01:15:50,380 --> 01:15:52,240 Play X there, nothing happens. 1692 01:15:52,240 --> 01:15:55,330 What I'd like to do now is to have some ability such 1693 01:15:55,330 --> 01:15:57,580 that when I click on a particular cell, it's 1694 01:15:57,580 --> 01:16:01,480 going to play a move in that particular place. 1695 01:16:01,480 --> 01:16:04,080 And so how am I going to do that? 1696 01:16:04,080 --> 01:16:07,170 Well, in application dot pi I'm going to add some [INAUDIBLE].. 1697 01:16:07,170 --> 01:16:09,000 I'm going to add a route. 1698 01:16:09,000 --> 01:16:12,110 I'm going to go after the index route. 1699 01:16:12,110 --> 01:16:16,410 I'm going to add a new route called play. 1700 01:16:16,410 --> 01:16:18,960 And this route is going to be a variable route. 1701 01:16:18,960 --> 01:16:22,260 I can go to different routes based on where on the board 1702 01:16:22,260 --> 01:16:23,910 I want to play the next move. 1703 01:16:23,910 --> 01:16:28,750 So I might say play int colon row. 1704 01:16:28,750 --> 01:16:30,140 Int again, is the type. 1705 01:16:30,140 --> 01:16:32,810 Row is just going to be the name of this variable. 1706 01:16:32,810 --> 01:16:38,670 And then slash int colon call for column. 1707 01:16:38,670 --> 01:16:42,836 And I'm just going to call this function play, which takes a row and a column. 1708 01:16:42,836 --> 01:16:44,460 And for now, I'm just going to return-- 1709 01:16:44,460 --> 01:16:47,970 1710 01:16:47,970 --> 01:16:51,914 right now I'm just going to return play to move. 1711 01:16:51,914 --> 01:16:53,330 It's not going to do anything yet. 1712 01:16:53,330 --> 01:16:56,090 It's just going to say OK, you played a move, even though you haven't yet. 1713 01:16:56,090 --> 01:16:57,881 And so what this is going to allow me to do 1714 01:16:57,881 --> 01:17:01,290 is if I go to slash play slash one slash one, 1715 01:17:01,290 --> 01:17:04,200 then it's going to play a move in row one column one, 1716 01:17:04,200 --> 01:17:07,180 or at least that's the goal. 1717 01:17:07,180 --> 01:17:10,360 So now if I go back here unexpected [INAUDIBLE]?? 1718 01:17:10,360 --> 01:17:12,160 Did I not save? 1719 01:17:12,160 --> 01:17:14,010 Better? 1720 01:17:14,010 --> 01:17:15,370 I see the game board. 1721 01:17:15,370 --> 01:17:17,050 I click on a place to play. 1722 01:17:17,050 --> 01:17:18,410 OK, nothing happened just yet. 1723 01:17:18,410 --> 01:17:18,910 Why? 1724 01:17:18,910 --> 01:17:22,450 Because I didn't actually say these links should go to that route. 1725 01:17:22,450 --> 01:17:24,490 So let's the next thing I need to do. 1726 01:17:24,490 --> 01:17:28,000 Inside of game dot HTML, these links I want 1727 01:17:28,000 --> 01:17:33,590 to go to this play function passing in some value for the row 1728 01:17:33,590 --> 01:17:34,790 and for the column. 1729 01:17:34,790 --> 01:17:38,620 There is some special syntax you can use here that we didn't see in CS50, 1730 01:17:38,620 --> 01:17:42,700 but that's actually quite powerful, a function called URL for. 1731 01:17:42,700 --> 01:17:46,330 It basically generates the URL based on the values 1732 01:17:46,330 --> 01:17:49,250 that you want to plug into the particular spots. 1733 01:17:49,250 --> 01:17:52,480 And so I'll show you the code here, just so you've seen it once. 1734 01:17:52,480 --> 01:17:56,140 We're going to go Curly Brace Curly Brace to mean plug in something here. 1735 01:17:56,140 --> 01:17:58,790 And I'm going to plug in URL for. 1736 01:17:58,790 --> 01:18:02,740 And the argument to URL for is the name of the function 1737 01:18:02,740 --> 01:18:04,570 that I want to bring the user to. 1738 01:18:04,570 --> 01:18:07,300 And the function I want to bring the user to in this case 1739 01:18:07,300 --> 01:18:09,570 is just called play. 1740 01:18:09,570 --> 01:18:12,460 So I'm going to redirect to URL for play. 1741 01:18:12,460 --> 01:18:14,660 But play as a function takes two arguments. 1742 01:18:14,660 --> 01:18:17,110 It takes row and it takes call. 1743 01:18:17,110 --> 01:18:21,280 So URL for also lets me specify what should the value of row be, 1744 01:18:21,280 --> 01:18:24,030 and what should the value of call be? 1745 01:18:24,030 --> 01:18:27,550 And so what should the value of row be in this case? 1746 01:18:27,550 --> 01:18:28,220 I, OK. 1747 01:18:28,220 --> 01:18:29,710 And the value of call? 1748 01:18:29,710 --> 01:18:30,970 J. All right, great. 1749 01:18:30,970 --> 01:18:35,590 So I'm redirecting the play row I column J. 1750 01:18:35,590 --> 01:18:37,750 Let's give this a try. 1751 01:18:37,750 --> 01:18:39,700 Refresh the page, nothing seems to happen. 1752 01:18:39,700 --> 01:18:43,010 But if I try and play in the upper left for example, 1753 01:18:43,010 --> 01:18:46,250 what it takes me to is up there in the URL bar 1754 01:18:46,250 --> 01:18:51,380 you see slash play slash zero slash zero, row zero column zero. 1755 01:18:51,380 --> 01:18:53,270 And it says, all right, you played a move. 1756 01:18:53,270 --> 01:18:56,390 I've been taken to a route that's dependent upon the row and the column 1757 01:18:56,390 --> 01:18:57,920 where by now I can actually play that move. 1758 01:18:57,920 --> 01:18:59,586 Right now of course, it doesn't do that. 1759 01:18:59,586 --> 01:19:01,702 1760 01:19:01,702 --> 01:19:04,910 After I play a move, I'm probably going to run some logic inside of this play 1761 01:19:04,910 --> 01:19:09,290 function that updates sessions square bracket board and also 1762 01:19:09,290 --> 01:19:12,260 updates session square bracket turn. 1763 01:19:12,260 --> 01:19:19,160 And then at the end, I probably want to redirect myself back to the index page. 1764 01:19:19,160 --> 01:19:24,110 And I can say URL for index to say redirect myself back 1765 01:19:24,110 --> 01:19:26,310 to the index function. 1766 01:19:26,310 --> 01:19:33,400 I'll need to import both redirect and URL for in to Flask. 1767 01:19:33,400 --> 01:19:37,690 But now if I run this application, I see an empty game board. 1768 01:19:37,690 --> 01:19:40,390 I press the place where I want to make a move. 1769 01:19:40,390 --> 01:19:43,210 And it takes me, redirects me back to the same game board. 1770 01:19:43,210 --> 01:19:45,940 And what you want to be able to do is have the move actually 1771 01:19:45,940 --> 01:19:49,180 appear there by updating the board. 1772 01:19:49,180 --> 01:19:53,710 And so before I move on, questions about anything 1773 01:19:53,710 --> 01:19:58,819 we've done so far, about the goals, about why we did things the way we did? 1774 01:19:58,819 --> 01:20:00,238 Anything about that? 1775 01:20:00,238 --> 01:20:03,290 1776 01:20:03,290 --> 01:20:03,790 All right. 1777 01:20:03,790 --> 01:20:07,054 Then what I think we'll do now is in a moment after I get some instructions, 1778 01:20:07,054 --> 01:20:10,220 we'll break out into smaller groups, and we'll actually try working on this. 1779 01:20:10,220 --> 01:20:12,303 I'll post this starter source code on the website, 1780 01:20:12,303 --> 01:20:14,570 if you haven't been following along quite exactly. 1781 01:20:14,570 --> 01:20:17,780 But first step is get the application working up to this point, 1782 01:20:17,780 --> 01:20:21,320 just so you can display the board, see places where you can play moves. 1783 01:20:21,320 --> 01:20:24,740 But the big step is going to be to implement this play function now, 1784 01:20:24,740 --> 01:20:28,130 this idea of OK, if I want to play in this row in this column, 1785 01:20:28,130 --> 01:20:30,620 update the board, change whose turn it is, 1786 01:20:30,620 --> 01:20:32,870 and then redirect back to the index page. 1787 01:20:32,870 --> 01:20:35,960 And then if you manage to finish that before the hour is up, 1788 01:20:35,960 --> 01:20:39,000 the next feature to implement is the idea of a reset game button. 1789 01:20:39,000 --> 01:20:41,300 Add a button to the bottom of the web page that 1790 01:20:41,300 --> 01:20:43,830 just says reset game, whereby if you click it, 1791 01:20:43,830 --> 01:20:46,480 it resets the game back to its original state. 1792 01:20:46,480 --> 01:20:49,850 And so think about how you might want to go about implementing that. 1793 01:20:49,850 --> 01:20:51,950 We'll work on that for about an hour or so. 1794 01:20:51,950 --> 01:20:53,647 We'll break for lunch at 12:30. 1795 01:20:53,647 --> 01:20:56,480 We'll reconvene back here at 2 PM where we'll talk a little bit more 1796 01:20:56,480 --> 01:20:58,760 about Flask, talk about artificial intelligence 1797 01:20:58,760 --> 01:21:00,740 and how to program artificial intelligence. 1798 01:21:00,740 --> 01:21:03,114 And then we'll spend the rest of the afternoon continuing 1799 01:21:03,114 --> 01:21:04,430 to work on this project. 1800 01:21:04,430 --> 01:21:06,530 We'll go ahead and break up into groups again. 1801 01:21:06,530 --> 01:21:09,980 And which group has not been here in the auditorium yet? 1802 01:21:09,980 --> 01:21:10,960 I think this group. 1803 01:21:10,960 --> 01:21:12,950 So this group will stay here in the auditorium. 1804 01:21:12,950 --> 01:21:16,760 We'll have you all go to room 136. 1805 01:21:16,760 --> 01:21:18,950 And you all go to room 212. 1806 01:21:18,950 --> 01:21:22,050 And the teaching fellows will spread out and help you there as well. 1807 01:21:22,050 --> 01:21:24,800 I'll post the source code online so you can begin working on that. 1808 01:21:24,800 --> 01:21:27,220 And we'll go until 12:30. 1809 01:21:27,220 --> 01:21:28,078