CS50 Week 6 & Week 6 Continued

Using the cs50 library in Python and VENV

I’m going to show you something I wish I knew sooner.

Python has a program that allows you to setup a virtual environment that is completely walled off from your entire computer. This means you can make a huge mess, write horrible messy code and install a ton of packages that break everything without worry of messing up your computer or other programs. Just exit the environment and delete the folder and you’re done. Keep in mind the folder only holds the environment data so you can write code even outside of your chosen directory.

To do this i’m going to go to my desktop and create a folder called cs50 and then go to that folder in my terminal window.

Make sure you’ve installed python 3 (google download python 3 to get it).

When working with virtual environments with python 3 you have to remember three steps:

  • create the env file using python3
  • startup the environment using source
  • exit the environment with a single command deactivate

So i’m in my cs50 folder in the terminal and i’m ready to create my environment folder. I know it seems confusing, isn’t cs50 the environment folder??? No, we are in cs50 to keep things nice and tidy. More on that in a second…

Let’s run our first command: python3 -m venv .env

So what just happened?

We are using the -m flag which is the command-line flag, to run the venv module as a script. So we’re basically running the venv python program.

the last bit is our argument we pass which is whatever we want to name our folder. I’m going to name it .env to make it a hidden folder (env just stands for environment so I know what it is for).

Now that we have our environment folder ready I can activate it. Still in the cs50 directory i’ll type: source .env/bin/activate

Now my terminal prompt changes so there is a (.env) at the beginning.

I can now install packages and run python3 without worrying about affecting other projects.

Finally if I want to save all my packages I can run this command:

pip freeze > requirements.txt

This creates a text file that has all the packages my project is currently using which I can then install on any other machine by typing:

pip install -r requirements.txt

And that is the way to create a clean directory with a .env file and a requirements file. Run the freeze command anytime you are finished with a project so it is up to date.

If you were putting your whole project into the cs50 folder it’s very convenient to zip it up, send it to someone and have them spin up the same environment from their computer without any issue!

  • So let’s save a file in the CS50 IDE, hello.py, with the following contents:print("hello, world")
  • Then, we can run python hello.py and see this:$ python hello.py hello, world
    • python is the name of the interpreter program that we’ve installed onto the CS50 IDE, and hello.py is the name of our file that we are passing in as an argument, for it to interpret.

Lecture and Python

The first lecture for the week was done at Yale university and is very hard to follow. It gave me flashbacks of all those days trying to figure out the C problem sets.

Moving on to the next lecture, we’re back at Harvard learning Python. Python is a “productivity” language. It’s easier to use than most other languages and has the added benefit of strict indentation. So your code looks just like my code (indent wise anyways). I have made some pretty basic programs in Python and get the gist of how it works. So this week was yet another breeze! Heading forward to week 7 in record time!

Python Basics (explained in a python program)

Here is a program I’ve written that goes through all the python basics in the lecture:

  • If we were to just import cs50 without the from statement, we would have access to cs50 as an object. This means to get to the get_string function we would have to write it as cs50.get_string(“name: “). By using the from statement we have direct access to that function in our program.
  • using f before a string allows special formatting, for example using variables by wrapping them in curly brackets. Because a string is an object with methods built in, we can also use “mystring {}”.format(myvariable). Using f”string {variable}” is a built in shortcut.
  • __name__ is a “special variable” that holds the name of either the main program or the file name where a program is being run. By default the program file I am working in will be “__main__” inside the __name__ variable. If I had a separate file I imported that would have it’s file name associated with the __name__ variable from within itself. Here is a quick example:

    create a file called cow.py with the following code:
print(f"I am a cow and the __name__ is = {__name__}")

if __name__ == "__main__":
    print("mooooo")
else:
    print("I must be running in the duck file!\n")

Next create another file called duck.py with the following code:

import cow

print(f"I am a duck and the __name__ is = {__name__}")

if __name__ == "__main__":
    print("quaaaack")
else:
    print("I am not a duck")

Running cow.py and then duck.py will show how __name__ is interpreted differently depending on the file being run.

Python Operators

My gist is slightly different from the cs50 notes. Better to re-write it in my own way to really learn more deeply.

The floor division is interesting. It truncates everything after the decimal point. So if you give it 2 integers it returns an integer back. Normal division will return a float.

If at anytime you want to know the type of something, use the type() function which is a part of the standard library of python, which means it just works out of the box!

Python Logic

Logic is very clean in python. Not a lot of braces to deal with. Indentation is important and code will break if things are not indented correctly. Makes looking at code slightly easier (very slightly for me at this point).

Instead of using && and || python uses the actual words or/and which is easier to read, in my opinion.

Using == also works with strings for comparison just like chars.

Defining functions

While looking at the notes on functions everything looked straightforward until I hit this “**” operator. It took a minute to realize python has another operator just for giving you the result of a number to the power of another number. So if I wrote 4**8 I would be saying 4 to the power of 8.

When writing functions we don’t use the function keyword we use def. No curly braces required as long as we indent everything within the function after the colon.

When dealing with longer lines of strings you can break them up as shown above. Just keep in mind if there are variables in your string you have to start each new line with the f character so python knows it’s an “f-string.”

Validate user input

I learned a few things from this example. I always get sloppy when trying to validate user input. In short you have to:

  • while true
  • if this meets my criteria (if the value is true)
  • break out
  • return the value

So while true, if true break and return! Input validated.

Also you can create multiline comments in your code by using triple quotation marks like so: ”’

Remember that main() is run at the very end so we can define it at the top and add the other functions later.

Integer overflow

The sleep function is cool for creating a delay. It’s amazing how python has a library for just about everything.

Mario…again

This took a good 30 minutes to sort out in my head. I found the end argument to be super helpful, but don’t forget to explicitly write a print() statement wherever you want an actual line break. By stating end=”” you are saying print this to stdout but don’t include a line break at the end just put nothing at the end. This is also helpful if for some reason every string in your loop needs to have something at the end that is repeated. Maybe a list of names and you just want to say {name}, end=” is awesome!” print().

Command line arguments

If we want access to the program name and any command line arguments when the program is about to run we can import the sys library which is a part of the standard python library. Here is a quick example:

As an added bonus there is a loop that goes through each string argument and then iterates through each character. It is the most readable loop in a loop ever.

Extract a user’s initials

In the cs50 notes for python lecture 8 there is an example for getting a user’s initials from their full name. It looks like this:

# Extracts a user's initials

from cs50 import get_string

s = get_string("Name: ")
initials = ""
for c in s:
    if c.isupper():
        initials += c
print(initials)

I wanted to see if I could figure out a way to get the users initials even if they didn’t capitalize the letters.

This is an opportunity to learn new things, jump into stackoverflow and overcome challenges. Do not feel bad for getting code off stackoverflow! It’s documentation of people spending hours figuring out edge case issues, and if you go there for something in particular over and over you will eventually memorize it. If it is an edge case you are better off leaving it out of your brain to focus on more important things! I did not copy and paste the entire script from someone else. If I got stuck on a small piece I worked through it with help from googling the question.

So I use regex every so often at my job, and it comes in super handy for getting the right bits of text, validating it so you only get what you want. It can be hard to visualize and figure out how to get the right groups.

Regex is a huge topic I won’t discuss here but, I will say check out https://regex101.com/ if you want to learn more.

So here is my initial generator! No capitals required, plus you can have as many names as you want and you will get initials forever!

Linear search in python

We can find an item in either a list of dictionary by using the in operator. It is a straightforward process. I made a quick list and a dictionary to both confirm an item in a list and then bring up an associated price for the item.

Comparing two strings

I created a slightly different version here where I did not use an else branch. sys.exit(0) is a function that will exit out of the program with a code of zero which means program ran successfully. If the string is equal it will pass over that branch and continue to the final print function.

Null and none

get_string can return a value known in python as none. It’s basically null I think!

Swapping values

We touched upon this in my big python program at the top. Packing and unpacking allows us to swap values in one line like this:

x = 1
y = 2

print(f"x is {x}, y is {y}")
x, y = y, x
print(f"x is {x}, y is {y}")

Data structures (classes)

Notice how this gist has 2 files. As long as they are in the same folder from student import Student should work just fine. Creating an object from a class is the same as a function call. We use the class name and the arguments from the __init__ method from inside the class. We don’t need to include self when we create the object because self is a reserved keyword used to bind each argument that it follows. So we’re creating the object and binding name and dorm to that particular instance. So a class is just a template, or a mold for an actual object. When create an instance of the class, we fill the mold and pop out an object.

After gathering the user input in a loop and pushing each one in our list using the append list method, we run a loop printing each student object within our students list.

Saving data to a file in python

This confused me at first because in the example I was under the impression the csv library we import included this weird with open statement. Check this out:

# Demonstrates file I/O

import csv
from cs50 import get_string
from student import Student

# Space for students
students = []

# Prompt for students' names and dorms
for i in range(3):
    name = get_string("name: ")
    dorm = get_string("dorm: ")
    students.append(Student(name, dorm))

with open("students.csv", "w") as file:
    writer = csv.writer(file)
    for student in students:
        writer.writerow((student.name, student.dorm))

So at the bottom we have this new section where we take out students and create a .csv file, which is just a simple spreadsheet table.

with open (“students.csv”, “w”) as file: is all in the box standard python stuff. We are creating a file handler, which I talk about in a previous post.

Without the with statement we have to remember to close our file handler like in C. Using with we can forget about it, python takes care of closing the file handler for us.

Our fancy csv library comes with a method called writer that takes in a file handler and gives us a writer object. That object has a method called writerow that takes in a tuple which we wrap in parenthesis and writes that data one row at a time into our file. In my example I push column headers into the first row before the loop starts.

What a dictionary class looks like in python

Almost done with the week 6 notes and i’m hit with this dictionary class! So lets try to break this all down:

class Dictionary:
    """Implements a dictionary's functionality"""

    def __init__(self):
        self.words = set()

    def check(self, word):
        """Return true if word is in dictionary else false"""
        return word.lower() in self.words

    def load(self, dictionary):
        """Load dictionary into memory, returning true if successful else false"""
        file = open(dictionary, "r")
        for line in file:
            self.words.add(line.rstrip("\n"))
        file.close()
        return True

    def size(self):
        """Returns number of words in dictionary if loaded else 0 if not yet loaded"""
        return len(self.words)

    def unload(self):
        """Unloads dictionary from memory, returning true if successful else false"""
        return True

I’m going to have to go back and get the list of dictionary words from that challenge way back when. I will create a gist with the file. Back in a few…

Week 4’s speller walkthrough! So I found the txt of words to load into our dictionary. So let’s see this in action:

from dictionary import Dictionary

dictionary = Dictionary()

print(dictionary.load('large'))

print(dictionary.size())

sample_text = []

with open('aca.txt', 'r') as file:
    for line in file:
        line = line.split()
        for word in line:
            if word[0].isalpha():
                sample_text.append(word.strip())


with open('spell_check.txt', 'w') as file:
    for word in sample_text:
        if not dictionary.check(word):
            file.write(word + '\n')
            print(f'{word} not in dictionary!')

So you need the week for files which i’ve included a link to here. This gives you a zip file with all the files from that challenge.

This is nothing special and barely does what it should do. BUT the actual “correct” program was barely doing a good job spell checking so i’m ready to move on!

Leave a Reply

avatar
  Subscribe  
Notify of