15 hours 57 minutes 47 seconds
🇬🇧 English
Speaker 1
07:00:00
In the code that you've written. All right, that's it for this week. We'll see you next time. All right, This is CS50's introduction to programming with Python.
Speaker 1
07:00:36
My name is David Malan. And this is our week on FileIO, input and output of files. So up until now, almost every program we've written just stores all the information that it collects in memory, that is, in variables or inside of the program itself. A downside of which is that as soon as the program exits, anything you typed in, anything that you did with that program, is lost.
Speaker 1
07:00:56
Now, with files, of course, on your Mac or PC, you can hang on to information long term. And file I-O, within the context of programming, is all about writing code that can read from, that is, load information from, or write to, that is, save information to, files themselves. So let's see if we can't transition then from only using memory and variables and the like to actually writing code that saves some files for us and therefore data persistently. Well, to do this, let me propose that we first consider a familiar data structure, a familiar type of variable that we've seen before, that of a list.
Speaker 1
07:01:29
And using lists, we've been able to store more than 1 piece of information in the past. Using 1 variable, we typically store 1 value. But if that variable is a list, we can store multiple values. Unfortunately, lists are stored in the computer's memory.
Speaker 1
07:01:42
And so once your program exits, even the contents of those disappear. But let's at least give ourselves a starting point. So I'm over here in VS Code, and I'm going to go ahead and create a simple program using code of names.py, a program that just collects people's names, students' names, if you will. And I'm going to do it super simply initially, in a manner consistent with what we've done in the past to get user input and print it back out, I'm going to say something like this.
Speaker 1
07:02:06
Name equals input, quote unquote, what's your name, thereby storing in a variable called name the return value of input, as always. And as always, I'm going to go ahead and very simply print out a nice f string that says, hello, comma, and then in curly braces, name, to print out, hello, David, hello, world, however he happens to be using the program. Let me go ahead and run this, just to remind myself what I should expect. And if I run Python of names.py and hit Enter, type in my name like David, of course, I now see hello, David.
Speaker 1
07:02:36
Suppose, though, that we wanted to add support not just for 1 name, but multiple names, maybe 3 names, for the sake of discussion so that we can begin to accumulate some amount of information in the program, such that it's really going to be a downside if we keep throwing it away once the program exits. Well, let me go back into names.py up here at top. Let me proactively give myself a variable, this time called names plural, and set it equal to an empty list. Recall that the square bracket notation, especially if nothing's inside of it, just means give me an empty list that we can add things to over time.
Speaker 1
07:03:10
Well, what do we want to add to it? Well, let's add 3 names, each from the user. And let me say something like this. For underscore in range of 3, let me go ahead and prompt the user with the input function and getting their name in this variable.
Speaker 1
07:03:25
And then using list syntax, I can say names.append name to that list. And now I have in that list that given name, 123 of them. Other points to note is I could use a variable here like I, which is conventional. But if I'm not actually using I explicitly on any subsequent lines, I might as well just use underscore, which is a Pythonic convention.
Speaker 1
07:03:48
And actually, if I want to clean this up a little bit right now, notice that my name variable doesn't really need to exist because I'm assigning it a value and then immediately appending it. Well, I could tighten this up further by just getting rid of that variable altogether and just appending immediately the return value of input. I think we could go both ways in terms of design here. On the 1 hand, it's a pretty short line, and it's readable.
Speaker 1
07:04:11
On the other hand, if I were to eventually change this phrase to be not what's your name, but something longer, we might want to break it out again into 2 lines. But for now, I think it's pretty readable. Now, later in the program, let's just go ahead and print out those same names. But let's sort them alphabetically so that it makes sense to be gathering them all together, then sorting them and printing them.
Speaker 1
07:04:31
So how can I do that? Well, in Python, the simplest way to sort a list in a loop is probably to do something like this. For name in names, but wait, let's sort the names first. Recall that there's a function called sorted, which will return a sorted version of that list.
Speaker 1
07:04:47
Now let's go ahead and print out an f string that says, again, hello, bracket name, close quotes. All right, let me go ahead and run this. So python of names.py. And let me go ahead and type in a few names this time.
Speaker 1
07:05:01
How about Hermione? How about Harry? How about Ron? And notice that they're not quite in alphabetical order.
Speaker 1
07:05:09
But when I hit Enter and that loop kicks in, it's going to print out, hello, Harry, hello, Hermione, Hello, Ron, in sorted order. But of course, now, if I run this program again, all of the names are lost. And if this is a bigger program than this, that might actually be pretty painful to have to re-input the same information again and again and again. Wouldn't it be nice, like most any program today, on a phone or a laptop or desktop or cloud to be able to save this information somehow instead.
Speaker 1
07:05:37
And that's where file I O comes in. And that's where files come in. They are a way of storing information persistently on your own phone or Mac or PC or some cloud server's disk so that they're there when you come back and run the program again. So how can we go about saving all 3 of these names in a file as opposed to having to type them again and again?
Speaker 1
07:06:00
Let me go ahead and simplify this file and, again, give myself just a single variable called name and set the return value of input equal to that variable. So what's your name as before? Quote, unquote. And now let me go ahead and let me do something more with this value.
Speaker 1
07:06:15
Instead of just adding it to a list or printing it immediately out, let's save the value of the person's name that's just been typed in to a file. Well, how do we go about doing that? Well, in Python, there's this function called open, whose purpose in life is to do just that, to open a file, But to open it up programmatically so that you, the programmer, can actually read information from it or write information to it. So open is like the programmer's equivalent of double clicking on an icon on your Mac or PC.
Speaker 1
07:06:42
But it's a programmer's technique because it's going to allow you to specify exactly what you want to read from or write to that file. Formally, its documentation is here. And you'll see that its usage is relatively straightforward. It minimally just requires the name of the file that we want to open and, optionally, how we want to open it.
Speaker 1
07:07:00
So let me go back to VS Code here. And let me propose now that I do this. I'm going to go ahead and call this function called open, passing in an argument for names.txt, which is the name of the file I would like to store all of these names in. I could call it anything I want.
Speaker 1
07:07:16
But because it's going to be just text, it's conventional to call it something, dot txt. But I'm also going to tell the open function that I plan to write to this file. So as a second argument to open, I'm going to put literally quote unquote w for write. And that's going to tell Open to open the file in a way that's going to allow me to change the content.
Speaker 1
07:07:35
And better yet, if it doesn't even exist yet, it's going to create the file for me. Now, Open returns what's called a file handle, a special value that allows me to access that file subsequently. So I'm going to go ahead and sign it equal to a variable like file. And now I'm going to go ahead and quite simply write this person's name to that file.
Speaker 1
07:07:54
So I'm going to literally type file, which is the variable linking to that file, dot write, which is a function, otherwise known as a method that comes with open files, that allows me to write that name to the file. And then lastly, I'm going to quite simply going to go ahead and say file.close, which will close and effectively save the file. So these 3 lines of code here are essentially the programmer's equivalent to double clicking an icon on your Mac or PC, making some changes in Microsoft Word or some other program, and going to File, Save. We're doing that all in code with just these 3 lines here.
Speaker 1
07:08:28
Well, let's see now how this works. Let me go ahead now and run Python of names.py and Enter. Let's type in a name. I'll type in Hermione.
Speaker 1
07:08:41
Enter. All right. Where did she end up? Well, Let me go ahead now and type code of names.txt, which is a file that happens now to exist because I opened it in write mode.
Speaker 1
07:08:53
And if I open this in a tab, we'll see there's Hermione. Well, let's go ahead and run names.py once more. I'm going to go ahead and run Python of names.py, Enter. And this time, I'll type in Harry.
Speaker 1
07:09:06
Let me go ahead and run it 1 more time. And this time, I'll type in Ron. And now let me go up to names.txt, where hopefully, I'll see all 3 of them here. But no, I've just actually seen Ron.
Speaker 1
07:09:19
What might explain what happened to Hermione and Harry, even though I'm pretty sure I ran the program 3 times and I definitely wrote the code that writes their name to that file? What's going on here, do you think?
Speaker 2
07:09:33
I think because we are not appending them, we should append the names. Since we are writing directly, it is erasing the old content, and it is replacing with the last set of characters that we mentioned.
Speaker 1
07:09:48
DAVID MALAN LANDER-WALTZECKING Exactly. Unfortunately, quote unquote W is a little dangerous. Not only will it create the file for you, it will also recreate the file for you every time you open the file in that mode.
Speaker 1
07:09:57
So if you open the file once and write Hermione, That worked just fine, as we saw. But if you do it again for Harry, if you do it again for Ron, the code is working. But each time, it's opening the file and recreating it with brand new contents. So we had 1 version with Hermione, 1 version with Harry, and 1 final version with Ron.
Speaker 1
07:10:13
But ideally, I think we probably want to be appending, as Vishal says, each of those names to the file, not just clobbering, that is, overwriting the file each time. So how can I do this? It's actually a relatively easy fix. Let me go ahead and do this as follows.
Speaker 1
07:10:27
I'm going to first remove the old version of names.txt. And now I'm going to change my code to do this. I'm going to change the W quote unquote to just A quote unquote, A for append, which means to add to the bottom, to the bottom, to the bottom again and again. Now let me go ahead and rerun Python of names.py, Enter.
Speaker 1
07:10:46
I'll again start from scratch with Hermione, because I'm creating the file new. Notice that if I now do code of names.txt, Enter, we do see that Hermione is back. So after removing the file, it did get recreated, even though I'm using append, which is good. But now let's see what happens when I go back to my terminal.
Speaker 1
07:11:07
And this time I run Python of names.py again, this time typing in Harry. And let me run it 1 more time, this time typing in Ron. So hopefully this time, in that second tab, names.text, I should now see all 3 of them. But, but, but, but, this doesn't look ideal.
Speaker 1
07:11:24
What have I clearly done wrong? Something tells me, even though all 3 names are there, it's not going to be easy to read those back, unless you know where each name ends and begins.
Speaker 3
07:11:36
AUDIENCE 1 The English format is not correct. The English format is not correct. Like, they say it's not correct.
Speaker 3
07:11:43
It's concatenating them. DAVID MALAN
Speaker 1
07:11:45
It is. Well, it appears to be concatenating, but technically speaking, it's just appending to the file. First Hermione, then Harry, then Ron.
Speaker 1
07:11:55
It has the effect of combining them back to back, but it's not concatenating, per se. It really is just appending. Let's go to another hand here. What really have I done wrong?
Speaker 1
07:12:05
Or equivalently, how might I fix? It would be nice if there were some kind of gaps between each of the names so we could read them more cleanly.
Speaker 3
07:12:14
AUDIENCE 1. Hello. We should add a new line before we write a new name.
Speaker 1
07:12:20
DAVID MALAN GANNONDORF Good. We want to add a new line ourselves. So whereas print by default, recall, always outputs automatically a line ending of backslash n, unless we override it with the named parameter called end, write does not do that.
Speaker 1
07:12:32
Write takes you literally. And if you say write Hermione, that's it. You're getting the H through the E. If you say write Harry, you get the H through the Y.
Speaker 1
07:12:41
You don't get any extra new lines automatically. So if you want to have a new line at the end of each of these names, we've got to do that manually. So let me, again, close names.txt, and let me remove the current file. And let me go back up to my code here.
Speaker 1
07:12:55
And I can fix this in any number of ways, but I'm just going to go ahead and do this. I'm going to write out an f string that contains name and backslash n at the end. We could do this in different ways. We could manually print just the new line or some other technique.
Speaker 1
07:13:08
But I'm going to go ahead and use my f strings, as I'm in the habit of doing, and just print the name and the new line all at once. I'm going to Go ahead now and down to my terminal window, run Python of names.py again, Enter. We'll type in Hermione. I'm going to run it again, type in Harry.
Speaker 1
07:13:23
I'm going to type it again, and this time, Ron. Now I'm going to run code of names.txt and open that file. And Now it looks like the file is a bit cleaner. Indeed, I have each of the name on its own line, as well as a line ending, which ensures that we can separate 1 from the other.
Speaker 1
07:13:40
Now, if I were writing code, I bet I could parse, that is, read the previous file by looking at differences between lowercase and uppercase letters. But that's going to get messy quickly. Generally speaking, when storing data long term in a file, you should probably do it somehow cleanly, like doing 1 name at a time. Well, let's now go back.
Speaker 1
07:13:59
And I'll propose that this code is now working correctly, but we can design it a little bit better. It turns out that it's all too easy when writing code to sometimes forget to close files. And sometimes this isn't necessarily a big deal, but sometimes it can create problems. Files could get corrupted or accidentally deleted or the like, depending on what happens in your code.
Speaker 1
07:14:17
So it turns out that you don't strictly need to call close on the file yourself if you take another approach instead. More Pythonic when manipulating files is to do this, to introduce this other keyword called, quite simply, with, that allows you to specify that in this context, I want you to open and automatically close some file. So how do we use with? It simply looks like this.
Speaker 1
07:14:43
Let me go back to my code here. I've gotten rid of the close line. And I'm now just going to say this instead. Instead of saying file equals open, I'm going to say with open, then the same arguments as before.
Speaker 1
07:14:55
And somewhat curiously, I'm going to put the variable at the end of the line. Why? That's just the way this is done. You say with, you call the function in question, and then you say as, and specify the name of the variable that should be assigned the return value of open.
Speaker 1
07:15:10
Then I'm going to go ahead and indent the line underneath so that the line of code that's writing the name is now in the context of this with statement, which just ensures that automatically, if I had more code in this file down below, no longer indented, the file would be automatically closed as soon as line 4 is done executing. So it doesn't change what has just happened, but it does automate the process of at least closing things for us just to ensure I don't forget and so that something doesn't go wrong. But suppose now that I wanted to read these names from the file. All I've done thus far is write code that writes names to the file.
Speaker 1
07:15:45
But let's assume now that we have all of these names in the file. And heck, let's go ahead and add 1 more. Let me go ahead and run this 1 more time, python of names.py. And let's add in Draco to the mix.
Speaker 1
07:15:56
So now that we have all 4 of these names here, how might we want to read them back? Well, let me propose that we go into names.py now. Or we could create another program altogether. But I'm going to keep reusing the same name just to keep us focused on this.
Speaker 1
07:16:09
And now I'm going to write code that reads an existing file with Hermione, Harry, Ron, and Draco together. And how do I do this? Well, it's similar in spirit. I'm going to start this time with with, open.
Speaker 1
07:16:23
And then the first argument is going to be the name of the file that I want to open, as before. And I'm going to open it this time in read mode, quote unquote, R. And to read a file just means to load it, not to save it. And I'm going to name the return value file.
Speaker 1
07:16:37
And now I'm going to do this. And there's a number of ways I can do this. But 1 way to read all of the lines from the file at once would be this. Let me declare a variable called lines.
Speaker 1
07:16:46
Let me access that file and call a function or a method that comes with it called readLines. So if you read the documentation on File.io in Python, you'll see that open files come with a special method whose purpose in life is to read all of the lines from the file and return them to me as a list. So what this line 2 is doing is it's reading all of the lines from that file, storing them in a variable called lines. Now suppose I want to iterate over all of those lines and print out each of those names.
Speaker 1
07:17:15
For line in lines, this is just a standard for loop in Python. Lines is a list. Line is the variable that will be automatically set to each of those lines. Let me go ahead and print out something like, oh, hello, comma.
Speaker 1
07:17:30
And then I'll print out the line itself. All right, so let me go to my terminal window, run Python of names.py now. I have not deleted names.txt. So it still contains all 4 of those names.
Speaker 1
07:17:42
And hit Enter. And OK, it's Not bad, but it's a little ugly here. What's going on? When I ran names.py, it's saying hello to Hermione, to Harry, to Ron, to Draco.
Speaker 1
07:17:53
But there's these gaps now between the lines. What explains that symptom? If nothing else, it just looks ugly.
Speaker 4
07:18:02
It happens because in the text file, we have new line symbols in between those names. And the print always adds another new line at the end. So you use the same symbol twice.
Speaker 1
07:18:16
Perfect. And here's a good example of a bug, a mistake in a program. But if you just think about those first principles, like how do each of the lines of code work that I'm using, you should be able to reason exactly as Rafal did there to say that, all right, well, 1 of those new lines is coming from the file after each name. And then, of course, print, all of these weeks later, is still giving us for free that extra new line.
Speaker 1
07:18:36
So there's a couple possible solutions. I could certainly do this, which we've done in the past, and pass in a named argument to print, like end equals quote unquote. And that's fine. I would argue a little better than that might actually be to do this, to strip off of the end of the line the actual new line itself so that print is handling the printing of everything, the person's name as well as the new line.
Speaker 1
07:18:59
But you're just stripping off what is really just an implementation detail on the file. We chose to use new lines in my text file to separate 1 name from another. So arguably, it should be a little cleaner in terms of design to strip that off and then let print print out what is really just now a name. But that's ultimately a design decision.
Speaker 1
07:19:18
The effect is going to be exactly the same. Well, if I'm going to open this file and read all the lines and then iterate over all of those lines and print them each out, I could actually combine this into 1 thing. Because right now, I'm doing twice as much work. I'm reading all of the lines.
Speaker 1
07:19:34
Then I'm iterating over all of the lines just to print out each of them. Well, in Python with files, you can actually do this. I'm going to erase almost all of these lines now, keeping only the with statement at top. And inside of this with statement, I'm going to say this.
Speaker 1
07:19:50
For line in file, go ahead and print out, quote unquote, hello, comma, and then line.rstrip. So I'm going to take the approach of stripping off the end of the line. But notice how elegant this is, so to speak. I've opened the file in line 1.
Speaker 1
07:20:06
And if I want to iterate over every line in the file, I don't have to very explicitly read all the lines, then iterate over all of the lines. I can combine this into 1 thought. In Python, you can simply say for line in file. And that's going to have the effect of giving you a for loop that iterates over every line in the file 1 at a time.
Speaker 1
07:20:24
And on each iteration, updating the value of this variable line to be Hermione, then Harry, then Ron, then Draco. So this, again, is 1 of the appealing aspects of Python is that it reads rather like English for line and file, print this. It's a little more compact when written this way. Well, what if, though, I don't want quite this behavior?
Speaker 1
07:20:45
Because notice now, if I run python of names.py, it's correct. I'm seeing each of the names and each of the hellos, and there's no extra spaces in between. But just to be difficult, I'd really like us to be sorting these hellos. Really, I'd like to see Draco first, then Harry, then Hermione, then Ron, no matter what order they appear in the file.
Speaker 1
07:21:06
So I could go in, of course, to the file and manually change the file. But if that file is changing over time based on who is typing their name into the program, that's not really a good solution. In code, I should be able to load the file no matter what it looks like and just sort it all at once. Now, here is a reason to not do what I've just done.
Speaker 1
07:21:24
I can't iterate over each line in the file and print it out, but sort everything in advance. Logically, if I'm looking at each line 1 at a time and printing it out, it's too late to sort. I really need to read all of the lines first without printing them, sort them, then print them. So we have to take a step back in order to add now this new feature.
Speaker 1
07:21:45
So how can I do this? Well, let me combine some ideas from before. Let me go ahead and start fresh with this. Let me give myself a list called names and assign it an empty list, just so I have a variable in which to accumulate all of these lines.
Speaker 1
07:21:59
And now Let me open the file with open quote, unquote, names.txt. And it turns out I can tighten this up a little bit. It turns out if you're opening a file to read it, you don't need to specify quote, unquote, R. That is the implicit default.
Speaker 1
07:22:12
So you can tighten things up by just saying open names.txt, and you'll be able to read the file, but not write it. I'm going to give myself a variable called file, as before. I am going to iterate over the file in the same way for line and file. But instead of printing each line, I'm going to do this.
Speaker 1
07:22:28
I'm going to take my names list and append to it. And this is appending to a list in memory, not appending to the file itself. I'm going to go ahead and append the current line. But I'm going to strip off the new line at the end so that all I'm adding to this list is each of the students' names.
Speaker 1
07:22:47
Now I can use that familiar technique from before. Let me go outside of this with statement, because now I've read the entire file, presumably. So by the time I'm done with lines 4 and 5, again and again and again for each line in the file, I'm done with the file. It can close.
Speaker 1
07:23:01
I now have all of the students' names in this list variable. Let me do this. For name in not just names, but the sorted names, using our Python function sorted, which does just that, and do print quote unquote with an f string, hello, comma, and now I'll plug in bracket name. So now what have I done?
Speaker 1
07:23:22
I'm creating a list at the beginning just so I have a place to gather my data. I then on lines 3 through 5 iterate over the file from top to bottom, reading in each line 1 at a time, stripping off the new line, and adding just the student's name to this list. And the reason I'm doing that is so that on line 7, I can sort all of those names, now that they're all in memory, and print them in order. I need to load them all into memory before I can sort them.
Speaker 1
07:23:48
Otherwise, I'd be printing them out prematurely and Draco would end up last instead of first. So let me go ahead in my terminal window and run Python of names.py now and hit Enter. And there we go, the same list of 4 hellos, But now they're sorted. And this is a very common technique when dealing with files and information more generally.
Speaker 1
07:24:06
If you want to change that data in some way, like sorting it, creating some kind of variable at the top of your program like a list, adding or appending information to it just to collect it in 1 place and then do something interesting with that collection. That list is exactly what I've done here. Now, I should note that if we just want to sort the file, we can actually do this even more simply in Python, particularly by not bothering with this names list nor the second for loop. And let me go ahead and instead just do more simply this.
Speaker 1
07:24:35
Let me go ahead and tell Python that we want the file itself to be sorted using that same sorted function, but this time on the file itself. And then inside of that for loop, Let's just go ahead and print right away our hello comma, followed by the line itself, but still stripping off of the end of it any white space therein. If we go ahead and run this same program now with Python of names.py and hit Enter, we get the same result. But of course, it's a lot more compact.
Speaker 1
07:25:00
But for the sake of discussion, let's assume that we do actually want to potentially make some changes to the data as we iterate over it. So let me undo those changes, leave things as is, whereby now we'll continue to accumulate all of the names first into a list, maybe do something to them, maybe forcing them to uppercase or lowercase or the like, and then sort and print out each item. Let me pause and see if there's any questions now on file I O, reading or writing, or now accumulating all of these values in some list. AUDIENCE 2
Speaker 5
07:25:29
Hi, Is there a way to sort the files, but instead, if you want it from alphabetically from A to Z, is there a way to reverse it from Z to A? Is there a little extension that you can add to the end to do that? Or would you have to create a new function?
Speaker 1
07:25:44
DAVID MALAN HANSON if you wanted to reverse the contents of the file?
Speaker 5
07:25:47
Yeah, so if you, instead of sorting them from A to Z in ascending order, if you wanted them in descending order, is there an extension for that?
Speaker 1
07:25:56
There is, indeed. And as always, the documentation is your friend. So if the goal is to sort them not in alphabetical order, which is the default, but maybe reverse alphabetical order, you can take a look, for instance, at the formal Python documentation there.
Speaker 1
07:26:08
And what you'll see is this summary. You'll see that the sorted function takes a first argument, generally known as an iterable. And something that's iterable means that you can iterate over it. That is, you can loop over it 1 thing at a time.
Speaker 1
07:26:20
What the rest of this line here means is that you can specify a key, like how you want to sort it, but more on that later. But this last named parameter here is reverse. And by default, per the documentation, it's false. It will not be reversed by default.
Speaker 1
07:26:34
But if we change that to true, I bet we can do that. So let me go back to VS Code here and do just that. Let me go ahead and pass in a second argument to sorted, in addition to this iterable, which is my names list. Iterable, again, in the sense that it can be looped over.
Speaker 1
07:26:49
And let me pass in reverse equals true, thereby overriding the default of false. Let me now run python of names.py. And now, Ron's at the top, and Draco's at the bottom. So there, too, whenever you have a question like that moving forward, consider what does the documentation say and see if there's a germ of an idea there.
Speaker 1
07:27:07
Because odds are, if you have some problem, odds are some programmer before you have had the same question. Other thoughts?
Speaker 3
07:27:13
AUDIENCE 2 Can we limit numbers of names? And the second question, can we find specific name in list? DAVID MALAN LANDIS.
Speaker 1
07:27:23
Really good question. Can we limit the number of the names in the file? And can we find a specific 1?
Speaker 1
07:27:28
We absolutely could. If we were to write code, we could, for instance, open the file first, count how many lines are already there. And then if there's too many already, we could just exit with sys.exit or some other message to indicate to the user that, sorry, the class is full. As for finding someone specifically, absolutely.
Speaker 1
07:27:47
You could imagine opening the file, iterating over it with a for loop again and again, and then adding a conditional. Like if the current line equals equals Harry, then we found the chosen run. And you can print something like that. So you can absolutely combine these ideas with previous ideas, like conditionals, to ask those same questions.
Speaker 1
07:28:05
How about 1 other question on file IO?
Speaker 4
07:28:09
So I just thought about this function, like read all lines. And it looks like it's like separate all the lines by this special character a backslash and but it looks like we don't need it character in we we always strip it and it looks like some bad design of function. Why wouldn't we just strip it inside this function?
Speaker 4
07:28:40
DAVID MALAN
Speaker 1
07:28:41
ANDERSON A really good question. So we are, in my examples thus far, using rstrip to strip from the end of the line all of this white space, you might not want to do that. In this case, I am stripping it away because I know that each of those lines isn't some generic line of text.
Speaker 1
07:28:58
Each line really represents a name that I have put there myself. I'm using the new line just to separate 1 value from another. In other scenarios, you might very well want to keep that line ending because it's a very long series of text or a paragraph or something like that where you want to keep it distinct from the others. But it's just a convention.
Speaker 1
07:29:16
We have to use something, presumably, to separate 1 chunk of text from another. There are other functions in Python that will, in fact, handle the removal of that white space for you. ReadLines, though, does literally that, though. It reads all of the lines as is.
Speaker 1
07:29:32
Well, allow me to turn our attention back to where we left off here, which is just names, to propose that with names.txt, we have an ability, it seems, to store each of these names pretty straightforwardly. But what if we wanted to keep track of other information as well? Suppose that we wanted to store information, including a student's name and their house at Hogwarts, be it Gryffindor or Slytherin or something else. Well, where do we go about putting that?
Speaker 1
07:30:00
Hermione lives in Gryffindor, so we could do something like this in our text file. Harry lives in Gryffindor, so we could do that. Ron lives in Gryffindor, so we could do that. And Draco lives in Slytherin, so we could do that.
Speaker 1
07:30:11
But I worry here. But I worry now that we're mixing apples and oranges, so to speak. Like some lines are names, some lines are houses. So this probably isn't the best design, if only because it's confusing or it's ambiguous.
Speaker 1
07:30:24
So maybe what we could do is adopt a convention. And indeed, this is, in fact, what a lot of programmers do. They change this file not to be names.txt, but instead, let me create a new file called names.csv. CSV stands for comma separated values.
Speaker 1
07:30:38
And it's a very common convention to store multiple pieces of information that are related in the same file. And so to do this, I'm going to separate each of these types of data not with another new line, but simply with a comma. I'm going to keep each student on their own line, but I'm going to separate the information about each student using a comma instead. And so now we sort of have a two-dimensional file, if you will.
Speaker 1
07:31:01
Row by row, we have our students. But if you think of these commas as representing a column, even though it's not perfectly straight because of the lengths of these names, it's a little jagged, you can think of these commas as representing a column. And it turns out these CSV files are very commonly used when you use something like Microsoft Excel, Apple Numbers, or Google Spreadsheets, and you want to export the data to share with someone else as a CSV file. Or conversely, if you want to import a CSV file into your preferred spreadsheet software, like Excel or Numbers or Google Spreadsheets, you can do that as well.
Speaker 1
07:31:36
So CSV is a very common, very simple text format that just separates values with commas and different types of values, ultimately, with new lines as well. Let me go ahead and run code of students.csv to create a brand new file that's initially empty, and we'll add to it those same names, but also some other information as well. So if I now have this new file, students.csv, inside of which is 1 column of names, so to speak, and 1 column of houses. How do I go about changing my code to read not just those names, but also those names and houses so that they're not all on 1 line?
Speaker 1
07:32:10
We somehow have access to both type of value separately. Well, let me go ahead and create a new program here called students.py. And in this program, let's go about reading, not a text file per se, but a specific type of text file, a CSV, a comma separated values file. And to do this, I'm going to use similar code as before.
Speaker 1
07:32:29
I'm going to say with open quote unquote students.csv. I'm not going to bother specifying quote unquote arc, because again, that's the default. But I'm going to give myself a variable name of file. And then in this file, I'm going to go ahead and do this for line in file as before.
Speaker 1
07:32:46
And now I have to be a bit clever here. Let me go back to students.csv, looking at this file, and it seems that on my loop on each iteration, I'm going to get access to the whole line of text. I'm not going to automatically get access to just Hermione or just Gryffindor. Recall that the loop is going to give me each full line of text.
Speaker 1
07:33:06
So logically, what would you propose that we do inside of a for loop that's reading a whole line of text at once, but we now want to get access to the individual values, like Hermione and Gryffindor, Harry and Gryffindor. How do we go about taking 1 line of text and gaining access to those individual values, do you think? Just instinctively, even if you're not sure what the name of the functions would be.
Speaker 6
07:33:27
AUDIENCE 2 You can access it as you would if you were using a dictionary, like using a key and value. DAVID MALAN
Speaker 1
07:33:33
So ideally, we would access it using a key and value. But at this point in the story, all we have is this loop. And this loop is giving me 1 line of text at a time.
Speaker 1
07:33:42
I'm the programmer now. I have to solve this. There is no dictionary yet in question. How about another suggestion here?
Speaker 3
07:33:49
So you can somehow split the 2 words based on the comma.
Speaker 1
07:33:53
Yeah, even if you're not quite sure what function is going to do this, intuitively, you want to take this whole line of text, Hermione, Gryffindor, Harry, Gryffindor, and so forth, and split that line into 2 pieces, if you will. And it turns out wonderfully, the function we'll use is actually called split that can split on any characters, but you can tell it what character to use. So I'm going to go back into students.py.
Speaker 1
07:34:15
And inside of this loop, I'm going to go ahead and do this. I'm going to take the current line. I'm going to remove the whitespace at the end, as always, using rstrip here. And then whatever the result of that is, I'm going to now call split and quote, unquote, comma.
Speaker 1
07:34:30
So the split function or method comes with strings, strs in Python. Any str has this method built in. And if you pass in an argument like a comma, what this split function will do is split that current string into 123, maybe more pieces by looking for that character again and again. Ultimately, split is going to return to us a list of all of the individual parts to the left and to the right of those commas.
Speaker 1
07:35:00
So I can give myself a variable called row here. And this is a common paradigm. When you know you're iterating over a file, specifically a CSV, it's common to think of each line of it as being a row. And each of the values therein, separated by commas, is columns, so to speak.
Speaker 1
07:35:17
So I'm going to deliberately name my variable row, just to be consistent with that convention. And now what do I want to print? Well, I'm going to go ahead and say this. Print, how about the following?
Speaker 1
07:35:29
An f string that starts with curly braces. Well, how do I get access to the first thing in that row? Well, the row is going to have how many parts? 2.
Speaker 1
07:35:39
Because if I'm splitting on commas, and there's 1 comma per line, that's going to give me a left part and a right part, like Hermione and Gryffindor, Harry and Gryffindor. When I have a list like row, how do I get access to individual values? Well, I can do this. I can say row bracket 0.
Speaker 1
07:35:57
And that's going to go to the first element of the list, which should hopefully be the student's name. Then after that, I'm going to say is in. And I'm going to have another curly brace here for row bracket 1. And then I'm going to close my whole quote.
Speaker 1
07:36:10
So it looks a little cryptic at first glance. But most of this is just f-string syntax with curly braces to plug in values. And what values am I plugging in? Well, row again is a list, and it has 2 elements, presumably.
Speaker 1
07:36:22
Hermione in 1, and Gryffindor in the other, and so forth. So bracket 0 is the first element, because remember, we start indexing at 0 in Python. And 1 is going to be the second element. So let me go ahead and run this now and see what happens.
Speaker 1
07:36:37
Python of students.py, Enter. And we see Hermione's in Gryffindor, Harry's in Gryffindor, Ron is in Gryffindor, and Draco is in Slytherin. So we have now implemented our own code from scratch that actually parses, that is, reads and interprets a CSV file ultimately here. Now let me pause to see if there's any questions, but we'll make this even easier to read in just a moment.
Speaker 1
07:37:06
Any questions on what we've just done here by splitting by comma?
Speaker 2
07:37:10
So my question is, can we edit any line of code any time we want? Or the only option that we have is to append the lines. Or let's say if we want to, let's say, change Harry's house to, let's say, Slytherin or some other house.
Speaker 2
07:37:29
DAVID MALAN HANSON
Speaker 1
07:37:30
Yeah, a really good question. What if you want to, in Python, change a line in the file and not just append to the end? You would have to implement that logic yourself.
Speaker 1
07:37:39
So for instance, you could imagine now opening the file and reading all of the contents in, Then maybe iterating over each of those lines. And as soon as you see that the current name equals equals Harry, you could maybe change his house to Slytherin. And then it would be up to you, though, to write all of those changes back to the file. So in that case, you might want to, in simplest form, read the file once and let it close, then open it again, but open for writing and change the whole file.
Speaker 1
07:38:07
It's not really possible or easy to go in and change just part of the file. Though you can do it, it's easier to actually read the whole file, make your changes in memory, then write the whole file out. But for larger files, where that might be quite slow, you can be more clever than that. Well, let me propose now that we clean this up a little bit, because I actually think this is a little cryptic to read, row bracket 0, row bracket 1.
Speaker 1
07:38:30
It's not that well-written at the moment, I would say. But it turns out that when you have a variable that's a list, like row, you don't have to throw all of those variables into a list. You can actually unpack that whole sequence at once. That is to say, if you know that a function like split returns a list, but you know in advance that it's going to return 2 values in a list, the first and the second, you don't have to throw them all into a variable that itself is a list.
Speaker 1
07:38:59
You can actually unpack them simultaneously into 2 variables doing name comma house. So this is a nice Python technique to not only create, but assign automatically in parallel 2 variables at once rather than just 1. So this will have the effect of putting the name in the left, Hermione, and it will have the effect of putting Gryffindor, the house, in the right variable. And we now no longer have a row.
Speaker 1
07:39:22
We can now make our code a little more readable by now literally just saying name down here and, for instance, house down here. So just a little more readable, even though functionally, the code now is exactly the same. All right, so this now works. And I'll confirm as much by just running it once more.
Speaker 1
07:39:39
Python of students.py, Enter. And we see that the text is as intended. But Suppose for the sake of discussion that I'd like to sort this list of output. I'd like to say hello again to Draco first, then hello to Harry, then Hermione, then Ron.
Speaker 1
07:39:55
How can I go about doing this? Well, let's take some inspiration from the previous example where we were only dealing with names and instead do it with these full phrases. So and so is in house. Well, let me go ahead and do this.
Speaker 1
07:40:08
I'm going to go ahead and start scratch and give myself a list called students, equal to an empty list initially. And then with open students.csv as file, I'm going to go ahead and say this, for line in file. And then below this, I'm going to do exactly as before, name, comma, house, equals, the current line, stripping off the white space at the end, splitting it on a comma. So that's exact same as before.
Speaker 1
07:40:33
But this time, before I go about printing the sentence, I'm going to store it temporarily in a list so that I can accumulate all of these sentences and then sort them later. So let me go ahead and do this. Students, which is my list, dot append. Let me append the actual sentence I want to show on the screen.
Speaker 1
07:40:53
So another f string. So name is in house, just as before. But notice I'm not printing that sentence. I'm appending it to my list.
Speaker 1
07:41:01
Not a file, but to my list. Why am I doing this? Well, just because, as before, I want to do this. For student in the sorted students, I want to go ahead and print out students, like this.
Speaker 1
07:41:14
Well, Let me go ahead and run Python of students.py and hit Enter now. And I think we'll see, indeed, Draco is now first. Harry is second. Hermione is third.
Speaker 1
07:41:23
And Ron is fourth. But this is arguably a little sloppy, right? It seems a little hackish that I'm constructing these sentences. And even though I technically want to sort by name, I'm technically sorting by these whole English sentences.
Speaker 1
07:41:39
So it's not wrong. It's achieving the intended result. But it's not really well-designed because I'm just kind of getting lucky that English is reading from left to right. And therefore, when I print this out, it's sorting properly.
Speaker 1
07:41:50
It would be better, really, to come up with a technique for sorting by the students' names, not by some English sentence that I've constructed here on line 6. So to achieve this, I'm going to need to make my life more complicated for a moment, and I'm going to need to collect information about each student before I bother assembling that sentence. So let me propose that we do this. Let me go ahead and undo these last few lines of code so that we currently have 2 variables, name and house, each of which has name and the student's house, respectively.
Speaker 1
07:42:23
And we still have our global variable students. But let me do this. Recall that Python supports dictionaries. And dictionaries are just collections of keys and values.
Speaker 1
07:42:32
So you can associate something with something else, like a name with Hermione, like a house with Gryffindor. That really is a dictionary. So let me do this. Let me temporarily create a dictionary that stores this association of name with house.
Speaker 1
07:42:48
Let me go ahead and do this. Let me say that the student here is going to be represented initially by an empty dictionary. And just like you can create an empty list with square brackets, you can create an empty dictionary with curly braces. So give me an empty dictionary that will soon have 2 keys, name and house.
Speaker 1
07:43:04
How do I do that? Well, I could do it this way. Student, open bracket, name equals the student's name that we got from the line. Student, bracket, house equals the house that we got from the line.
Speaker 1
07:43:17
And now I'm going to append to the students list, plural, that particular student. Now, why have I done this? I've admittedly made my code more complicated. It's more lines of code.
Speaker 1
07:43:29
But I've now collected all of the information I have about students while still keeping track. What's a name? What's a house? The list, meanwhile, has all of the students' names and houses together.
Speaker 1
07:43:41
Now, why have I done this? Well, let me for the moment just do something simple. Let me do for student in students, and let me very simply now say, print the following f string, the current student with this name is in this current student's house. And now notice 1 detail.
Speaker 1
07:44:02
Inside of this f string, I'm using my curly braces as always. I'm using inside of those curly braces the name of a variable as always. But then I'm using not bracket 0 or 1, because these are dictionaries now, not lists. But why am I using single quotes to surround house and to surround name?
Speaker 1
07:44:23
Why single quotes inside of this f string to access those keys?
Speaker 4
07:44:33
Yes, because you have double quotes in that line 12. And so you have to tell Python to differentiate.
Speaker 1
07:44:41
Exactly, because I'm already using double quotes outside of the f string. If I want to put quotes around any strings on the inside, which I do need to do for dictionaries, because recall, when you index into a dictionary, you don't use numbers like lists, 0, 1, 2, onward. You instead use strings, which need to be quoted.
Speaker 1
07:44:59
But if you're already using double quotes, it's easiest to then use single quotes on the inside so Python doesn't get confused about what lines up with what. So at the moment, when I run this program, it's going to print out those hellos, but they're not yet sorted. In fact, what I now have is a list of dictionaries. Nothing is yet sorted.
Speaker 1
07:45:19
But let me tighten up the code, too, to point out that it doesn't need to be quite as verbose. If you're in the habit of creating an empty dictionary, like this on line 6, and then immediately putting in 2 keys, name and house, each with 2 values, name and house, respectively. You can actually do this all at once. So let me show you a slightly different syntax.
Speaker 1
07:45:37
I can do this. Give me a variable called student. And let me use curly braces on the right-hand side here. But instead of leaving them empty, let's just define those keys and those values now.
Speaker 1
07:45:47
Quote unquote name will be name, and quote unquote house will be house. This achieves the exact same effect in 1 line instead of 3. It creates a new non-empty dictionary containing a name key, the value of which is the student's name, and a house key, the value of which is the student's house. Nothing else needs to change.
Speaker 1
07:46:07
That will still just work so that if I again run Python of students.py, I'm still seeing those greetings, but they're still not quite actually sorted. Well, what might I go about doing here in order to, what could I do to improve upon this further? Well, we need some mechanism now of sorting those students. But unfortunately, you can't do this.
Speaker 1
07:46:30
We can't sort all of the students now because those students are not names like they were before. They aren't sentences like they were before. Each of the students is a dictionary. And it's non-obvious how you would sort a dictionary inside of a list.
Speaker 1
07:46:45
So ideally, what do we want to do? If at the moment we hit line 9, we have a list of all of these students, and inside of that list is 1 dictionary per student, and each of those dictionaries has 2 keys, name and house, wouldn't it be nice if there were a way in code to tell Python, sort this list by looking at this key in each dictionary. Because that would give us the ability to sort either by name, or even by house, or even by any other field that we add to that file. So it turns out we can do this.
Speaker 1
07:47:17
We can tell the sorted function not just to reverse things or not. It takes another positional, it takes another named parameter called key, where you can specify what key should be used in order to sort some list of dictionaries. And I'm going to propose that we do this. I'm going to first define a function temporarily, for now, called getName.
Speaker 1
07:47:39
And this function's purpose in life, given a student, is to quite simply return the student's name from that particular dictionary. So if student is a dictionary, this is going to return literally the student's name. And that's it. That's the sole purpose of this function in life.
Speaker 1
07:47:55
What do I now want to do? Well, now that I have a function that, given a student, will return to me the student's name, I can do this. I can change sorted to say, use a key that's equal to whatever the return value of getName is. And this now is a feature of Python.
Speaker 1
07:48:13
Python allows you to pass functions as arguments in to other functions. So getName is a function, sorted is a function, and I'm passing in getName to sorted as the value of that key parameter. Now, why am I doing that? Well, if you think of the getName function as just a block of code that will get the name of a student, that's handy because that's the capability that sorted needs.
Speaker 1
07:48:40
When given a list of students, each of which is a dictionary, sorted needs to know, How do I get the name of the student in order to do alphabetical sorting for you? The authors of Python didn't know that we were going to be creating students here in this class, so they couldn't have anticipated writing code in advance that specifically sorts on a field called student, let alone called name, let alone house. So what did they do? They instead built into the sorted function this named parameter key that allows us all these years later to tell their function sorted how to sort this list of dictionaries.
Speaker 1
07:49:13
So now watch what happens. If I run Python of students.py and hit Enter, I now have a sorted list of output. Why? Because now that list of dictionaries has all been sorted by the student's name.
Speaker 1
07:49:27
I can further do this. If, as before, we want to reverse the whole thing by saying reverse equals true, we can do that too. Let me rerun python of students.py and hit Enter. Now it's reversed.
Speaker 1
07:49:37
Now it's Ron, then Hermione, Harry, and Draco. But we can do something different as well. What if I want to sort, for instance, by house name reversed? I could do this.
Speaker 1
07:49:47
I could change this function from getName to getHouse. I could change the implementation up here to be getHouse. And I can return not the student's name, but the student's house. And so now, notice, if I run Python of students.py, Enter, notice now it is sorted by house in reverse order.
Speaker 1
07:50:07
Slytherin is first, and then Gryffindor. If I get rid of the reverse, but keep the get house and rerun this program, now it's sorted by house. Gryffindor is first, and Slytherin is last. And the upside now of this is because I'm using this list of dictionaries and keeping the students' data together until the last minute when I'm finally doing the printing, I now have full control over the information itself.
Speaker 1
07:50:31
And I can sort by this or that. I don't have to construct those sentences in advance like I rather hackishly did the first time. That was a lot. Let me pause here to see if there are questions.
Speaker 4
07:50:43
So when we are sorting the files, every time should we use the loops or like a dictionary or any kind of list? Can we sort by just sorting, not looping or any kind of stuff?
Speaker 3
07:51:02
DAVID MALAN ANDERSON
Speaker 1
07:51:02
A good question. And the short answer with Python alone, you're the programmer. You need to do the sorting.
Speaker 1
07:51:09
With libraries and other techniques, absolutely. You can do more of this automatically because someone else has written that code. What we're doing at the moment is doing everything from scratch ourselves. But absolutely, with other functions or libraries, some of this could be made more easily done.
Speaker 1
07:51:25
Some of this could be made easier. Other questions on this technique here?
Speaker 3
07:51:30
It equal to the return value of the function. Can it be equal to just a variable or a value?
Speaker 1
07:51:43
Well, yes, it should equal a value. And I should clarify, actually, since this was not obvious. So when you pass in a function like getName or getHouse to the sorted function as the value of key, that function is automatically called by the sorted function for you on each of the dictionaries in the list.
Speaker 1
07:52:06
And it uses the return value of get name or get house to decide what strings to actually use to compare in order to decide which is alphabetically correct. So this function, which you pass just by name, you do not pass in parentheses at the end, is called by the sorted function in order to figure out for you how to compare these same values.
Speaker 4
07:52:28
AUDIENCE 2
Speaker 3
07:52:29
How can we use nested dictionaries? I have read about nested dictionaries. What is the difference between nested dictionaries and the dictionary inside a list?
Speaker 3
07:52:41
I think it is a DAVID MALAN
Speaker 1
07:52:42
ANDERSON Sure. So we are using a list of dictionaries. Why?
Speaker 1
07:52:47
Because each of those dictionaries represents a student. And a student has a name and a house. And we want to, I claim, maintain that association. And it's a list of students because we've got multiple students, 4 in this case.
Speaker 1
07:52:57
You could create a structure that is a dictionary of dictionaries. But I would argue it just doesn't solve a problem. I don't need a dictionary of dictionary. I need a list of key value pairs right now.
Speaker 1
07:53:07
That's all. So let me propose if we go back to students.py here and we revert back to the approach where we have getName as the function, both used and defined here. And that function returns the student's name. What happens to be clear is that the sorted function will use the value of key, getName in this case, calling that function on every dictionary in the list that it's supposed to sort.
Speaker 1
07:53:35
And that function getName returns the string that sorted will actually use to decide whether things go in this order, left, right, or in this order, right, left. It alphabetizes things based on that return value. So notice that I'm not calling the function getName here with parentheses. I'm passing it in only by its name so that the sorted function can call that getName function for me.
Speaker 1
07:53:57
Now, it turns out, as always, If you're defining something, be it a variable or in this case a function, and then immediately using it, but never once again needing the name of that function, like getName, we can actually tighten this code up further. I can actually do this. I can get rid of the getName function altogether, just like I could get rid of a variable that isn't strictly necessary. And instead of passing key, the name of a function, I can actually pass key what's called in a lambda function, which is an anonymous function, a function that just has no name.
Speaker 1
07:54:30
Why? Because you don't need to give it a name if you're only going to call it in 1 place. And the syntax for this in Python is a little weird. But if I do key equals literally the word lambda, then something like student, which is the name of the parameter I expect this function to take, And then I don't even type the Return key.
Speaker 1
07:54:48
I instead just say student bracket name. So what am I doing here with my code? This code here that I've highlighted is equivalent to the getName function I implemented a moment ago. The syntax is admittedly a little different.
Speaker 1
07:55:03
I don't use def. I didn't even give it a name like getName. I instead am using this other keyword in Python called lambda, which says, hey, Python, here comes a function, but it has no name. It's anonymous.
Speaker 1
07:55:15
That function takes a parameter. I could call it anything I want. I'm calling it student. Why?
Speaker 1
07:55:20
Because this function that's passed in as key is called on every 1 of the students in that list, every 1 of the dictionaries in that list. What do I want this anonymous function to return? Well, given a student, I want to index into that dictionary and access their name so that the string Hermione and Harry and Ron and Draco is ultimately returned. And that's what the sorted function uses to decide how to sort these bigger dictionaries that have other keys, like house, as well.
Speaker 1
07:55:50
So if I now go back to my terminal window and run python of students.py, it still seems to work the same. But it's arguably a little better designed, because I didn't waste lines of code by defining some other function, calling it in 1 and only 1 place. I've done it all sort of in 1 breath, if you will. All right, let me pause here to see if there's any questions specifically about lambda or anonymous functions and this tightening up of the code.
Speaker 3
07:56:17
And I have a question, like whether we could define lambda twice.
Speaker 1
07:56:22
You can use lambda twice. You can create as many anonymous functions as you'd like, and you generally use them in contexts like this, where you want to pass to some other function a function that itself does not need a name. So you can absolutely use it in more than 1 place.
Speaker 1
07:56:37
I just have only 1 use case for it. How about 1 other question on lambda or anonymous functions specifically? AUDIENCE
Speaker 4
07:56:43
2 What if our Lambda would take more than 1 line, for example. DAVID MALAN LANDERS, MD, PhD Sure.
Speaker 1
07:56:51
If your lambda function takes multiple parameters, that is fine. You can simply specify commas followed by the names of those parameters, maybe x and y or so forth, after the name student. So here, too, lambda looks a little different from def in that you don't have parentheses, you don't have the keyword def, you don't have a function name.
Speaker 1
07:57:10
But ultimately, they achieve that same effect. They create a function anonymously and allow you to pass it in, for instance, as some value here. So let's now change students.csv to contain not students' houses at Hogwarts, but their homes where they grew up. So Draco, for instance, grew up in Malfoy Manor.
Speaker 1
07:57:28
Ron grew up in The Burrow. Harry grew up in number 4, Privet Drive. And according to the internet, no 1 knows where Hermione grew up. The movies apparently took certain liberties with where she grew up.
Speaker 1
07:57:43
So for this purpose, we're actually going to remove Hermione because it is unknown exactly where she was born. So we still have some 3 students. But if anyone can spot the potential problem now, how might this be a bad thing? Well, let's go and try and run our own code here.
Speaker 1
07:57:58
Let me go back to students.py here. And let me propose that I just change my semantics, because I'm now not thinking about Hogwarts houses, but the students' own home. So I'm just going to change some variables. I'm going to change this house to a home, this house to a home, as well as this 1 here.
Speaker 1
07:58:15
I'm still going to sort the students by name, but I'm going to say that they're not in a house, but rather from a home. So I've just changed the names of my variables in my grammar in English here, ultimately, to print out that, for instance, Harry is from number 4 Privet Drive, and so forth. But let's see what happens here when I run Python of this version of students.py having changed students.csv to contain those homes and not houses. Enter.
Speaker 1
07:58:42
Huh. Our first value error. Like the program just doesn't work. What might explain this value error, the explanation of which rather cryptically is too many values to unpack, and the line in question is this 1 involving split?
Speaker 1
07:59:00
How did all of a sudden, after all of the successful runs of this program, did line 5 suddenly now break?
Speaker 3
07:59:07
In the line, in students.csv, you have 3 values. There's a line that you have 3 values in students.
Speaker 1
07:59:15
Yeah, I spent a lot of time trying to figure out where every student should be from so that we could create this problem for us. And wonderfully, the first sentence of the book is number 4, Privet Drive. And so the fact that that address has a comma in it is problematic.
Speaker 1
07:59:30
Why? Because you and I decided some time ago to just standardize on commas, CSV, comma separated values, to denote the, we standardized on commas in order to delineate 1 value from another. And if we have commas grammatically in the student's home, we're clearly confusing it as this special symbol. And the split function is now, for just Harry, trying to split it into 3 values, not just 2.
Speaker 1
07:59:57
And that's why there's too many values.
Omnivision Solutions Ltd