Adding Choices and Repetition to Your Study Log
This chapter is the project checkpoint for Part 2. The study log you built the previous part handled exactly one session — ask, respond, exit. This part, it grows into something that actually feels like a tracker: it handles many sessions in one run, it reacts differently to different sessions, and it ends with a small summary of what was logged.
What the Study Log Does Now
By the end of this checkpoint, your study log:
- Asks for sessions one at a time in a loop, until the user types
done. - Stores each session (subject and minutes) so the program can use it later.
- Reacts to each session with a different message depending on how long it was.
- Prints a summary at the end: the number of sessions, the total minutes, the average session length, and the longest session.
Nothing in this version saves data between runs. When you stop the program, everything you logged is gone. Persistence — actually saving to a file — arrives in Part 4. For now, the program is a single-run experience.
The Shape of the Main Loop
The main loop is the while True: ... break pattern from While Loops and Range. The skeleton looks like this:
subjects = []minutes_list = []
while True: subject = input("Subject (or 'done' to finish): ").strip().lower() if subject == "done": break
minutes_text = input("For how many minutes? ").strip() minutes = int(minutes_text)
subjects.append(subject) minutes_list.append(minutes)
# ... respond to this session here ...
# ... summary here, after the loop ...Read this carefully before writing your own version. Three things are worth noticing:
- The two lists,
subjectsandminutes_list, are set up before the loop. They start empty. The loop appends to them. - The check
if subject == "done": breakuses the normalized input (.strip().lower()), soDone,done, andDONEall work as quit signals. - The summary lives outside the loop. It only runs once, after the user has quit.
Indentation is what controls which lines are inside the loop and which are outside. Get that wrong and the summary will run on every iteration, or the appends will run after the loop — both common Part 2 bugs.
A Worked Second Version
Here is a complete working version. Your own version does not need to match this exactly.
print("=== Study Log ===")print()
subjects = []minutes_list = []
while True: subject = input("Subject (or 'done' to finish): ").strip().lower() if subject == "done": break
minutes_text = input("For how many minutes? ").strip() minutes = int(minutes_text)
subjects.append(subject) minutes_list.append(minutes)
# Response based on session length if minutes < 15: print(f" Short session on {subject} -- every bit counts.") elif minutes <= 90: print(f" Solid session on {subject}.") else: print(f" Long session on {subject} -- remember to take breaks!") print()
# Summaryprint("=== Summary ===")
if len(minutes_list) == 0: print("No sessions logged today.")else: total = 0 for m in minutes_list: total += m average = total / len(minutes_list)
longest = minutes_list[0] for m in minutes_list: if m > longest: longest = m
print(f"Sessions: {len(minutes_list)}") print(f"Total minutes: {total}") print(f"Average session: {average:.1f} minutes") print(f"Longest session: {longest} minutes")When you run this program and enter, say, Math for 45, Physics for 90, done — the output looks something like:
=== Study Log ===
Subject (or 'done' to finish): MathFor how many minutes? 45 Solid session on math.
Subject (or 'done' to finish): PhysicsFor how many minutes? 90 Solid session on physics.
Subject (or 'done' to finish): done=== Summary ===Sessions: 2Total minutes: 135Average session: 67.5 minutesLongest session: 90 minutesRead this program line by line and trace it with two sessions. Then trace it again with zero sessions (the user just types done immediately). The if len(minutes_list) == 0: guard is what keeps the empty case from crashing.
Why Parallel Lists?
You may notice that the program uses two separate lists — subjects and minutes_list — that need to be kept in sync. The first item of subjects corresponds to the first item of minutes_list, the second to the second, and so on. This is called parallel lists, and it has a real downside: nothing in the language stops you from accidentally appending to one list but not the other, and the two can get out of sync.
A more experienced programmer would probably use a dictionary or a small class to keep each session’s data together. That is exactly what you will learn in Part 6. For now, parallel lists are pedagogically clean: each list grows on its own, you can see exactly what is happening, and the loop patterns from Counting, Accumulating, and Searching apply directly.
When you switch the project to dictionaries in Part 6, you will get to feel the upgrade in a real way. That is more valuable than skipping straight to the polished version now.
Your Turn
Build your own version. Requirements:
- One
whileloop that keeps asking for sessions until the user typesdone. - At least one
if/elif/elsethat branches on something about the session (length, subject, or anything else you choose). - At least two parallel lists holding the session data.
- A summary at the end that uses at least two of the loop patterns from Counting, Accumulating, and Searching. Total and longest is one combination; total and “long-session count” is another; average and shortest is another.
- A reasonable response to the common edge cases:
- The user types
doneimmediately, before logging any sessions. The summary should not crash. - The user types
Doneordone(with a trailing space). The program should accept it. - A session of
0minutes should be handled sensibly. Whether that means accepting it, rejecting it, or just logging it is your choice — but the program should not crash.
- The user types
Study log with choices and repetition
0 / 20 points
Build the Week 2 study log.
Your program must:
- print an introduction line that includes
Study Log, - repeatedly ask for a subject until the user types
done, - accept
Done,DONE, anddoneas quit signals by normalizing the subject with.strip().lower(), - ask for minutes only after a non-quit subject,
- store subjects and minutes in two parallel lists,
- print a response for each logged session using
if/elif/else, - and print a summary after the loop.
The summary must include:
- the number of sessions,
- the total minutes,
- the average minutes rounded to one decimal place,
- and the longest session in minutes.
If no sessions are logged, print No sessions logged. and do not divide by zero.
Example input:
Math45Art90DoneRequired output text:
Study LogSolid session on math.Solid session on art.Sessions: 2Total minutes: 135Average minutes: 67.5Longest session: 90The exact input prompts may differ. The required output lines above must appear exactly as written.
Things to Try Beyond the Minimum
If you finish the minimum and want to keep going, here are some suggestions. None of these are required.
- Count sessions per subject. A loop that walks
subjectsand counts how many times each subject appears. Print the subject with the most sessions. - Find the most-studied subject by total minutes (not session count).
- Show a goal-progress message. Set a daily goal of, say, 120 minutes, and print how much of it the user hit.
- Reject zero-minute sessions with a polite message rather than logging them.
- Show all logged sessions in the summary as a numbered list, before the totals.
Each of these is small and gives you more practice with the loop patterns from this part.
Common Pitfalls
A short list of things that often trip students up on this project:
- Forgetting
int(...)inside the loop.minutesis text when it comes back frominput(...). The loop has to convert it before appending, or every comparison and total later will be wrong. - Not handling the empty case in the summary. If
doneis the first thing typed,minutes_listis empty. Dividing bylen(minutes_list)will crash. Theif len(minutes_list) == 0:guard is what fixes this. - Indentation putting the summary inside the loop. A subtle bug: the summary lines should be at the same indentation as the
while, not inside it. Otherwise the summary prints on every iteration. - Out-of-sync parallel lists. Appending to one list but not the other, usually because of an early
continueorbreak. Trace your loop with the empty-input case to catch this. - Quit signal not matching. Forgetting
.strip().lower(), soDonedoes not quit the program.
If you hit one of these, the right response is the same as the previous part: trace what is happening, add a debug print if needed, fix the one specific issue, and run again.