⑴
This is CS50, and this is finally week 6. And this is that week we promised, wherein we finally trasition from C, this lower-level older language via which we explored memory and how really computers work underneath the hood, to what's now called Python, which is a more modern, higher-level language, whereby we're still going to be able to solve the same types of problems. But it's going to suddenly start to get much, much easier because what Python offers, as do higher-level languages more generally, are what we might describe as abstractions over the very low-level ideas that you've been implementing in sections and problem sets and so much more.

But recall from week 0, where we began. This was our simplest of programs that just printed " hello,world ".

Things escalated quickly thereafter in week 1, where, suddenly, we had all of this new syntax. But the idea was still the same of just printing out " hello,world ".

Well, as of today, a lot of that distraction, a lot of the visual distraction, goes away entirely such that what used to be this in C will now be quite simply this in Python. And that's a bit of a head fake in that we're going to see some other fancier features of Python. But you'll find that Python's popularity in large part derives from just how relatively readable it is and also, as we'll ultimately see, just how exciting and filled the ecosystem amony Python programmers. That is to say there's a lot more libraries. There's a lot more problems that people have solved in Python that you can now incorporate into your own programs in order to stand on their shoulders and get real work done faster.

But recall, though, from C that we had a few steps via which to actually compile that kind of code, so we got into the habit of make to make our program called hello. And then we've been in the habit of running it with ./hello, the effect of which, of course, is to feed all of the zeros and ones that compose the hello program into the computer's memory and, in turn, the CPU.

We revealed that what make is really doing, is something a more specific, namely running clang, the C language compiler specifically, with some automatic command line arguments so as to output the name that you want, link in the library that you want, and so forth.

But with Python, wonderfully, we're going to get rid of those steps, too, and quite simply run it as follows. Henceforth, our programs will no longer be in files ending in .c, suffice it to say. Our files starting today are going to start ending with .py, which is an indication to the computer - - macOS, Windows, or Linux or anything else - - that this is a Python program. But unlike C, wherein we've been in the habit of compiling our code and running it, compiling our code and running it, any time you make a change, with Python, those two steps get reduced into one, such that any time you make a change and want to rerun your code, you don't explicitly compile it anymore. You instead just run a program called python, similar in spirit to clang. But whereas clang is a compiler, python will see as not only the name of the language, but the name of a program. And interpreter is a program that reads your code top to bottom, left to right and really does what it says without having this intermediate step of first having to compile it in zeros and ones. So with that said, let me do this.

Let me flip over here to VS Code. And within VS Code let me write my first Python program. And as always, I can create a new file with the code command within VS Code. I'm going to create this file called hello.py, for instance.

And quite, quite simply, I'm going to go ahead and simply do print ( " hello,world " ). And if I go down to my terminal window, instead of compiling this, I'm instead going to interpret this program by running python, space, and the name of the file I want. Python to interpret, hitting Enter. And volia. Now you see " hello,world ". But let me go ahead and compare this at left.

Let me also go ahead and bring back briefly a file called hello.c. And I'm going to do this as we did in the very first day of C, where I included standard io.h, I did int main ( void ), I did inside of there printf ( ), quote, uquote, hello,world, backslash n, semicolon.

And let me go ahead in VS Code. And if you drag your file over to the right or the left,

you can actually split-screen things if of help.

And what I've done here is - - and let me hide my terminal window - - I've now compared these two files left and right. So here's hello.c from, say, week 1. Here's hello.py from week 6 now. And the obvious - - the differences are perhaps obvious. But there's still some - - there's a subtlety at least one subtlety. Beyond getting rid of lots of syntax, what did I apparently omit from my Python version even though it didn't appear to behave in any buggy way ? The library. So I didn't have to include any kind of library like standard I/O library, print ( ), apparently, in Python, just works. So I don't need to use main ( ) anymore. So this main ( ) function, to be clear, was required in C because that's what told the compiler what the main part of your program is. And you can't just start writing code otherwise. What else do you see ?

So there's no more semicolon, wonderfully enough, at the end of this line, even though there was here. And things are getting a little more subtle now. What else ? So the new line. So recall that in printf ( ), if you wanted to move the cursor to the next line when you're done printing, you had to do it yourself. So it seems as though Python - - because when I interpreted this program a moment ago, the cursor did move to the next line on its own. They sort of reversed the default behavior.

So those are just some of the salient differences here. One, you don't have to explicitly include standard library, so to speak, like standard I/O. You don't need to define a main ( ) function anymore. You can just start writing your code. You don't need these parentheses, these curly braces, printf ( ) is now called print ( ), it would seem. And you don't need the backslash n. Now, there is one thing that's also a little looser, even though I don't do it here.

Even though in C, it was required to use double quotes any times you want to use a string, a.k.a, char *,

in Python, as with a lot of languages nowadays, you can actually get away with just using single quotes so long as you are consistent. Generally speaking, some people like this because you don't have to hold shift, and therefore, you just hit one key instead of two. So there's an argument in terms of efficiency. However, if you want to use an apostrophe in your string, then you have to escape it.

And so in general, stylistically, I'll use double quotes in this way. But things are getting a little looser now with Python whereby that's not actually a requirement. But what's especially exciting with Python, and really, a lot of higher-level languages, is just how much real work you can get done relatively quickly. So you've just spent quite a bit of time, daresay, implementing your spell checker and implementing your own dictionary of sorts. Well, let me propose that maybe we should have asked you to do that in Python instead of C. Why ?

Well, let me go ahead and do this. Let me go into a directory called speller that I downloaded in advance for class.

And if I type ls in here, you'll notice that it's very similar to what you spent time on with problem set 5. But the file extensions are different. There's a dictionary.py instead of dictionary.c. There's a speller.py instead of a speller.c. And there's the exact same directories, dictionaries, and texts that we gave you for problem set 5. So let me just stipulate that I spent time implementing speller.c in Python. And so I gave it a name of speller.py. But I didn't go about really implementing dictionary.py yet. And so why don't we go ahead and actually implement dictionary.py together by doing this ?

Let me clear my terminal, do code dictionary.py. And let me propose that we implement, ultimately, four functions. And what are those functions going to be ? Well, they're going to be the check ( ) function, the load ( ) function, the size ( ) function and the unload ( ) function. But recall that in problem set 5, you implemented your own hash table. And so while there isn't a hash table data type in Python, I'm going to go ahead and do this.

I'm going to create a variable, a global variable in dictionary.py, called words, and I'm going to make it a set. In the mathematical sense, a set is a collection of things that won't contain duplicates. Any duplicates will be filtered out.

So I'm going to now, after that, creating that one global variable, I'm going to create a function called check ( ), just as you did. And check ( ) takes as input a word.

And if I want to check if a word is in that set of words, I can simply do word.lower in words. And that's it.

Let me now define another function called load ( ), which, recall, took an argument, which was the name of the dictionary you want to load into memory. Inside of my load ( ) function, I'm now going to do this. I'm going to say with open ( dictionary ) as a variable called file. And in there, I'm going to go ahead and update the set of words to be the updated version of whatever's in this file as a result of reading it and then splitting its lines, whereby this file has a big, long column of words, each of which is separated by a new line, splitline is going to split all of those into one big collection. And then I'm just going to go ahead and return True.

I'm now going to go ahead and define a size function, just as you did. But in Python, I'm going to go ahead and just go ahead and return the length of that set of words, where length, or len ( ), is a function itself in Python.

And I'm going to do one last function. It turns out that in Python, even though, for this program, I'm going to go and implement a function called unload, there's not actually anything to unload in Python, because Python will manage your memory for you, malloc ( ) is gone, free ( ) is gone. Pointers are gone. It handles all of that seemingly magically for now, for you.

So here then is, I claim, what you could have done with problem set 5 if implementing it in Python instead.

Let me go ahead and open my terminal window. Let me increase its size. Let me run Python of speller.py, which is the name of the actual program, not the dictionary per se that I implemented.

Let's run it on a file called holmes.txt because that was a particularly big file. And if I hit Enter now, we'll see, hopefully.



the same output that you say in C flying across the screen.

And eventually, we should see that same summary at the bottom as to how many words seem to be misspelled, how many words were in the dictionary, and ultimately, how fast this whole process was.

Now the total amount of time required was 1.93 seconds, which was actually longer than it seemed to take. That's because we're doing this in the cloud and it was taking some amount of time to second all of the text to my screen. But the code was only taking 1.93 seconds total on the actual server. And hopefully, these same kinds of numbers line up with your own the difference being what I did not have to implement for this spell checker is your own hash table, is your own dictionary, literally, beyond what I've done using Python here with some of these built-in features. So why, you see, why not always use Python, assuming that you prefer the idea of being able to whip up within seconds the entirety of problem set 5 ? How might you choose now between languages ? And I apologize if you're harboring resentment that this wasn't a week earlier why Python or why C ? So you always thought that Python was slower than C and takes up more space than C. Odds are that's, in fact, correct. So even though, ultimately, this 1.93 seconds is still pretty darn fast, odds are it's a little slower than the C version would have been. It's possible, too, that my version in Python actually does take up more RAM or memory underneath the hood. Why ? Well, because Python itself is managing memory for you. And it doesn't necessarily know a priori how much memory you're going to need. You, the programmer might, and you, the programmer writing in C, allocated presumably exactly as much memory as you might have needed last week with problem set 5. But Python's get to maybe do its best effort for you and try to manage memory for you, and there's going to be some overhead.

The fact that I have so many fewer lines of code, the fact that these lines of code solve problem set 5 for me, means that Python, or whoever invented Python, they wrote lines of code to of give me this functionality. And so if you think of Python as a middle man of sorts, it's doing more work for me. It's doing more of the heavy lift. So it might take me a bit more time.

But, my gosh, look how much time it has saved in terms of writing this code more quickly. And arguably, this code is even more readable, or at least will be after today, week 6, once you have an eye for the syntax and features of Python itself.