WEBVTT 00:00:00.000 --> 00:00:03.000 Hi. Welcome to the second office hours. 00:00:03.000 --> 00:00:07.000 Again we had a lot of really good questions in the forum, so let's get started. 00:00:07.000 --> 00:00:12.000 The first question came from Matthew Atkinson. 00:00:12.000 --> 00:00:15.000 He has heard that you shouldn't use functions like eval and exec, 00:00:15.000 --> 00:00:17.000 which we did use in unit 2. 00:00:17.000 --> 00:00:20.000 He wants to know why shouldn't we be using these functions, 00:00:20.000 --> 00:00:22.000 and what's the problem with them. 00:00:22.000 --> 00:00:26.000 That's a great question. There's a couple reason to avoid these. 00:00:26.000 --> 00:00:30.000 On is for security, especially if you're going to be evaling 00:00:30.000 --> 00:00:35.000 a string that somebody passes in to you, you don't know what it's going to be doing. 00:00:35.000 --> 00:00:41.000 There are lots of dangerous commands that Python can execute like "delete all my files." 00:00:41.000 --> 00:00:45.000 You don't want to be asking somebody to type something in and then go execute that 00:00:45.000 --> 00:00:50.000 and allow them to do something dangerous. That's one reason. 00:00:50.000 --> 00:00:53.000 The other is just in terms of program structure. 00:00:53.000 --> 00:00:58.000 We like to write our programs so that the functions and variables and so on, 00:00:58.000 --> 00:01:00.000 have a set scope. 00:01:00.000 --> 00:01:03.000 This variable exists from here to here, 00:01:03.000 --> 00:01:06.000 and eval kind of breaks all that structure 00:01:06.000 --> 00:01:11.000 and goes outside of it and say now we're executing something right here, 00:01:11.000 --> 00:01:14.000 but it's not executing with respect to where we are in the code. 00:01:14.000 --> 00:01:19.000 It's executing someplace complete different. That makes it harder to follow the code. 00:01:19.000 --> 00:01:24.000 There's nothing wrong in terms of do you get the right answer but harder to understand. 00:01:24.000 --> 00:01:26.000 So we should minimize it. 00:01:26.000 --> 00:01:34.000 I used it in the assignment for week 2, because there was no other way to easily get around it. 00:01:34.000 --> 00:01:37.000 But you should minimize the use. 00:01:37.000 --> 00:01:40.000 Thanks. The next question comes from Sasheen. 00:01:40.000 --> 00:01:43.000 Sasheen want's to know a little bit more about this big-O notation 00:01:43.000 --> 00:01:46.000 that we introduced and saw a little bit of in Unit 2. 00:01:46.000 --> 00:01:52.000 Yeah. The answer to that question is a whole course in algorithms. 00:01:52.000 --> 00:01:54.000 We can't do that right here. 00:01:54.000 --> 00:02:00.000 But basically the idea is big O says approximately how many instructions 00:02:00.000 --> 00:02:02.000 is it going to take to execute this. 00:02:02.000 --> 00:02:05.000 Actually, big O is an upper bound on that. 00:02:05.000 --> 00:02:12.000 There's another notation less widely used with big theta which gives a more exact bound, 00:02:12.000 --> 00:02:19.000 but the idea is if I have a doubly nested loop that says for i = 1-n 00:02:19.000 --> 00:02:24.000 and then inside of that is nest for j = 1-n then that's the order n-squared, 00:02:24.000 --> 00:02:29.000 because we're going to n * n executions of the inner loop. 00:02:29.000 --> 00:02:35.000 The basic idea is that's more than if we were just doing what are n executions of the loop. 00:02:35.000 --> 00:02:39.000 So if you can get away with a single loop instead of a double loop, that's better. 00:02:39.000 --> 00:02:43.000 That's really all you need to know about big O. 00:02:43.000 --> 00:02:48.000 Alright. I should say there will be an algorithms class sometime in the near future 00:02:48.000 --> 00:02:51.000 for those of you who want to learn more about this. 00:02:51.000 --> 00:02:56.000 Thomas Grace had a question about these attributes you use--function attributes-- 00:02:56.000 --> 00:03:00.000 specifically in the C function that had c.starts and c.items. What's going on there? 00:03:00.000 --> 00:03:07.000 So Dave Evans in CS101 chose not to really focus on Python classes, 00:03:07.000 --> 00:03:10.000 which is probably a good choice, because it's a big topic. 00:03:10.000 --> 00:03:15.000 The idea here is that classes of objects can have attributes. 00:03:15.000 --> 00:03:19.000 These are parts or components of the object, 00:03:19.000 --> 00:03:25.000 and they're named with this dot-notation--object, dot, then the name of a field 00:03:25.000 --> 00:03:28.000 that's a component of that object. 00:03:28.000 --> 00:03:31.000 In most languages you define all the fields ahead of time. 00:03:31.000 --> 00:03:36.000 When you define what a class looks like, you say these are the fields that compose this object. 00:03:36.000 --> 00:03:41.000 Python is a more dynamic language, and some classes of objects you're allowed to add 00:03:41.000 --> 00:03:46.000 fields to them as you go, and functions are one of those types of dynamic objects 00:03:46.000 --> 00:03:51.000 where you can at any you say I want to add a new attribute to this function. 00:03:51.000 --> 00:03:56.000 Other objects have that same approach where you can add to it. 00:03:56.000 --> 00:04:01.000 And so what was going on in the C function is that I needed two variables 00:04:01.000 --> 00:04:04.000 that I wanted to keep track of something. I needed two counters. 00:04:04.000 --> 00:04:10.000 I could have just used a global variable name, but that would be cluttering up the name space. 00:04:10.000 --> 00:04:17.000 There'd be no way for you to, if I just made up a name like cstarts and citems-- 00:04:17.000 --> 00:04:20.000 by looking at the name of the variable you could figure out that they were related-- 00:04:20.000 --> 00:04:24.000 but there'd be no structural way to say that these are all related. They belong together. 00:04:24.000 --> 00:04:29.000 You want to minimize the number of global variables, because people's memories are small. 00:04:29.000 --> 00:04:34.000 By putting everything into one object, we say this belongs together. 00:04:34.000 --> 00:04:41.000 Using c.start rather than a variable named cstart is a way of structuring things together. 00:04:41.000 --> 00:04:44.000 In Python you can do that automatically. You don't have to have a declaration. 00:04:44.000 --> 00:04:49.000 You can just say I want to add a new attribute to a function, and you go ahead and assign it. 00:04:49.000 --> 00:04:53.000 Great. I had no idea you could do that either. I was very excited to see that. 00:04:53.000 --> 00:04:56.000 Yeah. If you come from a language like Java or C, you're not used to that. 00:04:56.000 --> 00:05:02.000 There you've got to declare ahead of time what your attributes are going to be. 00:05:02.000 --> 00:05:05.000 Right. Next question comes from Tracy Zelman, 00:05:05.000 --> 00:05:09.000 and she just wants to hear a little bit about when do we use lambdas. 00:05:09.000 --> 00:05:12.000 How do you decide when to use a normal function versus lambda. 00:05:12.000 --> 00:05:18.000 All a lambda is is a function definition without assigning a name to it. 00:05:18.000 --> 00:05:22.000 In a normal function definition we say "def", then we say the function name, 00:05:22.000 --> 00:05:24.000 the arguments, and the body of the function. 00:05:24.000 --> 00:05:26.000 We're simultaneously doing two things. 00:05:26.000 --> 00:05:31.000 We're defining what the function does, and we're giving it a name. 00:05:31.000 --> 00:05:34.000 Now, what a lambda does is break those out 00:05:34.000 --> 00:05:36.000 to say we're defining a function, but we're not giving it a name. 00:05:36.000 --> 00:05:38.000 Why would you want to do that? 00:05:38.000 --> 00:05:40.000 Well, we do it all the time. 00:05:40.000 --> 00:05:46.000 If we have an expression--like say we have the arithmetic expression x + 1 * x - 1, 00:05:46.000 --> 00:05:51.000 we didn't both to give names to those subcomponents--the x + 1 and the x - 1. 00:05:51.000 --> 00:05:55.000 We just wrote them down. So a lambda is like that. 00:05:55.000 --> 00:05:59.000 It's a function that's a small thing. We didn't want to bother giving it a name. 00:05:59.000 --> 00:06:02.000 We just wanted to use it in place. 00:06:02.000 --> 00:06:08.000 So that's the advantage of lambda that you aren't bothered with a name, 00:06:08.000 --> 00:06:11.000 and you can just write it right there without having to define it at one point 00:06:11.000 --> 00:06:14.000 and then use it at a second point. That's the good thing about it. 00:06:14.000 --> 00:06:17.000 The bad thing about it is that it's limited. 00:06:17.000 --> 00:06:20.000 In Python lambda can only have an expression. 00:06:20.000 --> 00:06:26.000 It can't have statements in it, and it just doesn't really fit with the rest of the language. 00:06:26.000 --> 00:06:30.000 Some languages are really designed around expressions like that, and they go really well. 00:06:30.000 --> 00:06:33.000 In Python it doesn't fit that much. 00:06:33.000 --> 00:06:39.000 I think mostly you should avoid it and just define a function with its name in the normal way, 00:06:39.000 --> 00:06:42.000 but sometimes it's really convenient to put everything in one place 00:06:42.000 --> 00:06:46.000 rather than having to define in one place and use in a second place. 00:06:46.000 --> 00:06:51.000 Great. Udacer had some questions about the program design strategy that we've been using. 00:06:51.000 --> 00:06:54.000 Namely, should we implement the strategy that we've been using 00:06:54.000 --> 00:06:58.000 in every single problem we approach? Is there somewhere we don't really need it? 00:06:58.000 --> 00:07:02.000 If we chose not to use the strategy, what are some of the disadvantages? 00:07:02.000 --> 00:07:07.000 Well, whatever you can do to get your job done, go ahead and do it. 00:07:07.000 --> 00:07:09.000 I've given you some approaches. 00:07:09.000 --> 00:07:13.000 I wouldn't say that there is just one strategy, but rather there is a collection of strategies 00:07:13.000 --> 00:07:16.000 that you want to be able to understand what's going on, 00:07:16.000 --> 00:07:19.000 make your inventory of concepts, 00:07:19.000 --> 00:07:23.000 build those up. You have a lot of choices within that. 00:07:23.000 --> 00:07:29.000 Do I want to start top down, bottom up, middle out? That's all up to you. 00:07:29.000 --> 00:07:33.000 As long as you arrive at the end of a description of the whole domain, 00:07:33.000 --> 00:07:39.000 and the whole program and you get it right, then congratulations to you. 00:07:39.000 --> 00:07:43.000 I think every body develops their own style for how they go about addressing this, 00:07:43.000 --> 00:07:47.000 but there are ideas of what it means to have a high-quality program-- 00:07:47.000 --> 00:07:50.000 correctness, efficiency, and so on. 00:07:50.000 --> 00:07:55.000 Then more driven by taste is what does it mean to be readable and extensible. 00:07:55.000 --> 00:07:58.000 You'll learn that over time. 00:07:58.000 --> 00:08:02.000 Great. For one last question, Takanzi wants to know if you have any good recommendations 00:08:02.000 --> 00:08:05.000 for computer science, and specifically Python, books. 00:08:05.000 --> 00:08:07.000 Oh, books. Okay. 00:08:07.000 --> 00:08:09.000 Yes, I do have some recommendations. 00:08:09.000 --> 00:08:14.000 If you search for Peter Norvig's library in Google Books, I have some there. 00:08:14.000 --> 00:08:19.000 With this question maybe I'll go and update them some more. 00:08:19.000 --> 00:08:21.000 I can mention a few. 00:08:21.000 --> 00:08:26.000 In terms of general programming books, I really like The Practice of Programming. 00:08:26.000 --> 00:08:30.000 I like The Elements of Programming Style, which is rather an old 00:08:30.000 --> 00:08:33.000 and somewhat dated book now in terms of the examples it uses, 00:08:33.000 --> 00:08:37.000 but still really up-to-date in terms of the advice. 00:08:37.000 --> 00:08:40.000 I like Structure and Interpretation of Computer Programs, 00:08:40.000 --> 00:08:46.000 which has been a standard textbook for introductory computer science. 00:08:46.000 --> 00:08:52.000 I like Programming Pearls is a nice collection of short essays. 00:08:52.000 --> 00:09:00.000 Then in Python books, there's a lot of them, and I haven't kept up with all the possibilities. 00:09:00.000 --> 00:09:05.000 There's a nice online book of How To Think Like a Computer Scientist that has a Python version. 00:09:05.000 --> 00:09:11.000 There's Python in a Nutshell, Python Cookbook, Learning Python. 00:09:11.000 --> 00:09:16.000 Headfirst Python, I think, is an interesting, somewhat different approach. 00:09:16.000 --> 00:09:20.000 There are a lot of them there, and I'll try to update my Google Books library 00:09:20.000 --> 00:09:24.000 to give a little bit of commentary on each one. 00:09:24.000 --> 00:09:28.000 Thank you. Thank you for all the question. Thank you for your answer. 00:09:28.000 --> 00:09:32.000 Stay tuned for the next unit, which will be posted on Sunday 00:09:32.000 --> 00:09:34.000 and also for a couple more editions to the Python glossary. 00:09:34.000 --> 00:09:37.000 All right. See you in class.