Wednesday, 10/14
Studio: functions and your personal website
Open in a new tab
· press f for fullscreen, o for an overview
TL;DR#
Today was a studio. We grew a few lines of BMI code into two functions and a program in scripts/bmi.py, and set up a personal website at <your-github-username>.github.io. The habit worth keeping: after every change, run it and check the result. A BMI of 0, a 200 with an empty reply and a website that still shows your README each came up today without an error message.
Reading a reply from a server#
A 200 means the server understood the request and answered. It does not mean the answer holds what you wanted. In the first poll, the town was spelled Wellesly, and the reply was {'generationtime_ms': 0.71}, with no results in it at all. Look at the reply before you use it.
Read nested data one layer at a time. In the second poll, reply is a dictionary, so len(reply) counts its keys: 2. reply["data"] is a list of two people, reply["data"][0] is the first person, a dictionary of three fields, and reply["data"][0]["city"] is "Boston". A position where a key belongs, as in reply["data"][0][2], stops with a KeyError.
To find one record in a list, loop and compare. With people a list of dictionaries:
for person in people:
if person["name"] == "Hiro":
print(person["city"], person["age"])Test it with a name that is in the list and with one that is not. The first version we tried in class printed nothing for a name that was missing and also nothing for a name that was there, and only the second test showed it was broken. Writing for name, city, age in people: does not work, because unpacking a dictionary gives you its keys: name holds the text "name" on every pass.
From a few lines to functions#
The steps and the check values are on today's slides. What each step taught:
A script runs from the root folder of your repository. uv run python scripts/bmi.py in VS Code's Terminal, with the Terminal open in the repository's root folder. If you have cd'd into scripts, the path no longer matches.
A function runs only when it is called. Wrapping the code in def classify_bmi(bmi): and running the file prints nothing until a line such as print(classify_bmi(27)) calls it. A function has to be defined above the line that calls it.
A parameter exists only while the function runs. When classify_bmi(bmi_value) is called, bmi inside the function takes the value of bmi_value; once the function returns, bmi is gone, and print(bmi) outside it stops with a NameError. Giving the outside variable a different name, as bmi_value, keeps the two apart.
Return the result; do not print it. A function that ends with print(category) shows the category and hands back None, so print(f"Your category is {classify_bmi(18)}") prints Your category is None. End it with return category, and the caller decides what to do with the result: print it, put it in a sentence, or count it. r/learnpython has thousands of threads on return and print.
A docstring says what a function takes and gives back. The string in triple quotes on the first line of the function appears when you hover over a call. With compute_bmi and classify_bmi each described that way, main() reads as the whole program: ask for two numbers, compute, classify, print. Breaking the problem into those pieces is decomposition, and calling a piece by what its docstring promises is abstraction.
A wrong unit gives a wrong number with no error. Typing 175 for a height in meters gives a BMI of 0.00 and the category Underweight. That is why the unit is in the input() prompt. Check with the slide's values first, 1.75 and 70 give 22.86 and Normal, and then try your own.
To type by hand, snooze the suggestions. VS Code's agent fills in code as you type. For a by-hand step, click the Copilot menu in the Status Bar and select Snooze, which turns inline suggestions off for five minutes (VS Code docs).
Why your agent writes if __name__ == "__main__":#
import bmi runs the whole of bmi.py, top to bottom. With main() on its last line, a second file that only wants compute_bmi would find itself asking for a height. Putting the call behind the guard stops that:
if __name__ == "__main__":
main()When you run bmi.py itself, main() runs. When another file imports it, only the definitions are loaded. You need this only once your program has more than one file, but you will see it in nearly every script an agent writes.
The loop variable is each item#
In for i in people:, i holds one person, a dictionary, on each pass. Calling it i does not make it a position. Name it for what it holds, person. Avoid max, min and sum as names, since Python already uses them.
Advanced
If you need the position as well,
for number, person in enumerate(people, start=1):gives you both.
Robots and AI#
The lightning talk was on how AI is changing robotics. A robot used to be programmed step by step for one task; now models learn from video of people doing the task and from demonstrations. Some points from the discussion after it:
- Data is the limit. A language model learned from the text of the internet, and no collection of robot movements comes close to that size. A robot trained for one task, such as loading a dishwasher, is within reach; one robot for every household task is not yet.
- A vision-language-action model is one model that takes camera images and an instruction and outputs the robot's next movements. Google DeepMind's RT-2 started from a model trained on web images and text and fine-tuned it on robot data, so that its output is a sequence of actions in place of a reply in words. π0 comes from Physical Intelligence, a startup.
Your personal website#
The repository name has to be exactly your GitHub username, followed by .github.io, in lowercase. Keep every hyphen and every digit: jane-doe-99 becomes jane-doe-99.github.io. Any other name, with a dot or an underscore in place of a hyphen, a dropped digit or a name of your own, does not give you https://<your-github-username>.github.io. To fix a wrong name, open the repository on github.com, then Settings, and change Repository name. GitHub Desktop follows the rename.
Check that the address shows your website. Each push starts a deploy, which shows as a dot beside the latest commit on the repository's page: yellow while it runs, a green check when it is done, a red cross when it failed. Today some deploys timed out on GitHub's side. If your address still shows the README, commit any small change and push again.
Everything on the page is public. Paste into the prompt only the parts of your resume you want anyone to read, and leave out your phone number and home address. Keep the resume file itself out of the repository.
To improve it, show the agent websites whose style you like, as links or screenshots, and commit after each change. On the repository's page, the gear beside About lets you show your website's address there. Checkpoint 3 checks only that your address opens; what goes on the page is up to you. Build it out over the term, and add your projects to it as you go.
Public links#
- Session page
- Today's slides, with the BMI steps and the website prompt
- Mini Project 2
- GitHub Pages quickstart
- Exercism's Python track, for practice on your own: Hello World, then Guido's Gorgeous Lasagna, Ghost Gobble Arcade Game and Meltdown Mitigation
Before next session#
- Mini Project 1 revision, by Sunday 10/18, a day earlier than the date shown in class. Fix everything in my comment, push, then reply under my comment on Canvas so that I know to grade it again. This is the only project with a revision.
- Mini Project 2 is due Sunday 10/25. Commit sections 1 and 2 alone, before any code or agent, with the message
mp2: plan before AI. Submit the link to your notebook insideprojects/mp2/. - Notebook 4, sections 1 to 3,
04-functions-and-apis.py, if you have not finished them. bmi.pyin thescriptsfolder, which sits in the root folder of your repository, besidenotebooks. If yours landed inside another folder, drag it out in VS Code's Explorer, and check that the folder is namedscripts, in lowercase. It is on Checkpoint 3, which closes Sunday 10/25.- Your website opens at
https://<your-github-username>.github.io. If it does not, rename the repository as above. This is on Checkpoint 3 too.
Next Wednesday, 10/21, we will do section 4 of notebook 4, then read a CSV file into a dataframe.