Learning to Code: Harvard CS50 Week 4 Libraries

This week was very conceptual. A lot of it was learning how to use modules and access data. we covered the following topics:

Modules. randomimportfromstatistics. Command-Line Arguments. syssys.argvIndexErrorsys.exit. Slices. Packages. PyPI. pipcowsay. APIs. requests. JSON. __name__.

Modules are functions defined in separate files that can be imported and used. Random is one of those modules, it is built into vs code.

from random import choice

coin = choice(["heads", "tails"])

print(coin)

import random

number = random.randint(1,10)
print(number)

cards = ["jack", "queen", "king"]
random.shuffle(cards)
for card in cards:
    print(card)

Here we are importing the random module into our code. Even though the random module comes preinstalled, we still have to import it. We can also use the from command to import only specific functions that don’t have to be prefixed with their module when called.

The statistics module is another module that comes pre-installed with vs code.

import statistics

print(statistics.mean([100, 90]))

Another module is sys. sys provides functions that work with the terminal. (The terminal being where you run your code.) the sys.argv function (argument v) creates an input from whats written in the initial command line.

import sys

try:
    print('hello, my name is', sys.argv[1])
except IndexError:
    print("Too few arguments")

For example, this file is called name.py so to run the program in the terminal I would write:

$ python name.py

But to input data on the command line I would write something like this:

$python name.py Theo

Then the program would run “hello, my name is Theo”. When using the argv the name of the file is the first value, so argv[0] would be name.py. Also, inputs in the command line are separated by a single space, so Theo Aronow would be two separate inputs and “Theo Aronow” would only be one. An error that can occur is IndexError which occurs when the program requires an argv input but none is given.

The next topic we covered was slices. Slices are basically when you take only a piece of a larger list of elements.

import sys

if len(sys.argv) < 2:
    sys.exit("Too few arguments")

for arg in sys.argv[1:]:
    print("hello, my name is", arg)

Here we are taking every argument input after the name of the file and printing it out using a for loop. If you want to take a slice from the middle, you would use the notation [1:-x] where is is the number of elements you want to subtract off of the end of the list.

Next, we covered packages, PYPi, pip, and cowsay. Packages are third-party libraries that can be installed and used. PYPi is a directory/repository of all available packages. pip is python’s package manager that can be used to install packages. Cowsay is a popular package that allows a cow to speak in the terminal. To install cowsay, you would type the following into the terminal:

pip install cowsay

import cowsay
import sys

if len(sys.argv) == 2:
    cowsay.trex("hello, " + sys.argv[1])

Here is an example of what the following code will look like.

Next we briefly covered API’s. API stands for application programming interface. They facilitate information between two programming systems. A lot of companies create API’s of their software so that third parties can use their information. In this example, Apple has an API for iTunes that provides information on songs. We can access this information with requests.

“JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page, or vice versa).” I stole this because I figured I would explain it poorly as I do not fully understand it yet. The json python module provides helpful commands for interacting with this data.

import requests
import sys
import json

if len(sys.argv) != 2:
    sys.exit()

response = requests.get("https://itunes.apple.com/search?entity=song&limit=50&term=" + sys.argv[1])


o = response.json()

for result in o["results"]:
    print(result["trackName"])

Here we are using the .get function to get the information on 50 songs of whatever artists the user types in. Then we print out all the track names.

Last, we covered __name__. This is a unique variable to python. When we are using a separate file like a module to import functions, and the separate file has a main() function that is being run – when a function is called it will also call the main function. To circumvent this we use the __name__ variable. the __name__ variable will be equal to __main__ when it is called in its own script, and when it is called from another script it will be equal to __(the name of the other script)__. So we can put a conditional on the main() function.

Problem 1: Emojize

For this problem we have to take a code/alias like :thumbsup: and convert it to an emoji. To do this I had to install the emoji package using pip install emoji. Then, I imported the package to my program. From there all I had to do was run my code through the emojize function and print it out. Pretty easy. I kept having a bug until I realized I needed to set my language = ‘alias’.

import emoji

text = input("Input: ")

print("Output:", emoji.emojize(text, language='alias'))

Problem 2: Figlet

In this problem we are using figlet, a program that creates block letters as a form of ASCII art. To do this we have two case scenarios, the first being when there is no command line input, indicating the user wants a random figlet font. The other means the user inputed either “-f” or “–font” as the first argument and the second argument was their desired font. All other inputs should result in sys.exit.

Then I used if statements to check what the conditions met were. If there was only the file name, I used the random module to randomly select a font from the list I created called “fonts”. Then I used figlet to render the text.

If the user selected a specific font I just rendered it in that font.

from pyfiglet import Figlet
import random
import sys

figlet = Figlet()

fonts = figlet.getFonts()

if len(sys.argv) == 1:
    font = choice(fonts)
    text = input("Input:")
    figlet.setFont(font=font)
    print(figlet.renderText(text))
elif len(sys.argv) == 3:
    if sys.argv[1] == "-f" or sys.argv[1] =="--font":
        if sys.argv[2] in fonts:
            text = input("Input:")
            figlet.setFont(font=sys.argv[2])
            print(figlet.renderText(text))
        else:
            sys.exit("Not a font")
    else:
        sys.exit("Wrong Argument")

else:
    sys.exit("Incorrect amount of arguments")

Problem 3: Adieu

In this problem we are building a list of names and then bidding adieu to them. We use the concepts from the grocery problem to build a list using a continuous loop. The prompt tells us we can use the inflect module (which you install). The inflect module gives us the command .join which turns our list into a single string with commas and “and”.

import inflect

inflect = inflect.engine()

names = []

while True:
    try:
        name = input("Name:").strip()
        names.append(name)
    except EOFError:
        print("")
        break

list_of_names = inflect.join(names)
print("Adieu, adieu, to", list_of_names)

Problem 4: Guessing Game

In this problem, the user is asked for a threshold number. The program then selects a number between 1 and the threshold number. The user is continuously asked to guess numbers in the range until they find the answer. The program tells them if their guess is too little or too high. This problem was pretty easy. All I had to do was create while loops and if-else conditionals within them.

import random

while True:
    try:
        level = int(input("Level:").strip())
        if level < 1:
            continue
        break
    except ValueError:
        continue
answer = random.randint(1, level)
while True:
    try:
        guess = int(input("Guess:").strip())
        if guess < 1:
            continue
    except ValueError:
        continue
    if guess < answer:
        print("Too Small!")
        continue
    elif guess > answer:
        print("Too large!")
    else:
        print("Just right!")
        break

Problem 5: Little Professor

In this problem the user will give a level which determines the numbers of integers in a set of 10 addition problems the user then must solve. The problem is presented to us using a main function with get_level() and generate_integers() functions we need to define.

The get_level() and generate_integers() functions were super easy to devise and didn’t really need to be separate functions. For the get_level function I just used a while loop until we got satisfactory input and if else statements to generate integers.

Then in the main() function I created a while loop to limit the amount of problems to 10. In the loop, each time it would generate new numbers to add and then in a nested while loop the user would input their answer. If they inputted the correct answer the score would increase by 1. If not they had 3 attempts to solve the problem before the correct answer would display. At the end the score would display.

import random


def main():
    score = 0
    problem = 0
    level = get_level()
    while problem < 10:
        attempt = 0
        a = generate_integer(level)
        b = generate_integer(level)

        try:
            while True:
                attempt += 1
                if attempt > 3:
                    print(a + b)
                    break
                user_answer = int(input(f"{a} + {b} =").strip())
                if user_answer == a + b and attempt == 1:
                    score += 1
                    break
                elif user_answer == a + b:
                    break
                else:
                    print("EEE")
                    continue
        except ValueError:
            attempt += 1
            print("EEE")
            continue

        problem += 1
    print(f"Score: {score}")


def get_level():
    while True:
        try:
            level = int(input("Level:").strip())
            if 0 < level < 4:
                return level
                break
        except ValueError:
            continue


def generate_integer(level):
    if level == 1:
        integer = random.randint(0, 9)
    elif level == 2:
        integer = random.randint(10, 99)
    else:
        integer = random.randint(100, 999)
    return integer

if __name__ == "__main__":
    main()

Problem 6: Bitcoin

This problem involved using a bitcoin API (application programming interface) to request a json that has information on the cryptocurrency Bitcoin. Basically I just followed the YouTube demo to use requests to get the current price of bitcoin and then multiplied it by the command line argument inputted amount. It was pretty easy.

import requests
import sys
import json

if len(sys.argv) != 2:
    sys.exit("missing command line argument")

try:
    n = float(sys.argv[1])
except ValueError:
    sys.exit("Not a number")

response = requests.get("https://api.coindesk.com/v1/bpi/currentprice.json").json()


price = response["bpi"]["USD"]["rate_float"] * n

print(f"${price:,.4f}")

I would say this weak was one of the more fun weeks I’ve had. However, I took a few weeks off between completing the challenge problems, which made it more difficult.