• Can you explain the difference between "import" (e.g. import os) and "from ... import *"?

    Sure. The first creates an object, os, that contains all the names in the os module. E.g. os.getuid

    The latter puts the name (or with *, all names into the current namespace, e.g. getuid. So, if you have your own function called getuid, they would conflict. But if you don't, you save yourself three characters of typing, but you sacrifice a bit of clarity. (Someone reading your code won't necessarily know that getuid is the one from the os module and not your home-grown function that happens to have the same name.

    Usually, clarity is more important than brevity, but there are occasions when programmers go the other way. Here, we are tearing down the wall between two files.

  • can we go over question 2. I know that A is a valid answer but I feel like D would also be a valid so I am a little confused.
    Given the following code:
    d = {}
    x = d.get('apple')
    
    A. Your program prints an error message
    B. Python raises an exception
    C. x has the value '' (the empty string)
    D. x has the value None

    Let's try it! We'll copy the code into a Python REPL and see what it does.

  • Could you go over question 5 (what happens when you use the .execute() method on a cursor object)?

    Glad to. When we invoke the curs.execute(sql,data) method:

    1. The SQL and the DATA are sent to the DBMS (the database server, which we typically describe just as "the database").
    2. The DBMS prepares the SQL, which is essentially a kind of compilation, like javac but on a single method.
    3. The compiled SQL is executed, with the DATA filled in, kinda like passing arguments to a compiled function/method.
    4. The resulting data is sent back to the client, which holds it in the cursor (the value of curs)

    After that, whenever we want the data, or part of the data, we can get it from the cursor by using curs.fetchone() or curs.fetchall().

  • In the people app, could we fetch all of the people (people.get_people(conn)) on the function to execute before the first request? Doing something like that could make sense for an app that works with some type of information (such as all people) in many places.

    Interesting! This is essentially a kind of pre-fetching (or pre-computation) and caching.

    There are lots of occasions in which this would be a great idea, saving the need to get the data multiple times from the database and avoiding delay on the first (well, sorta).

    But, if the database changes, the cached data would be out of date.