Week 11 — Coding Lab / Programming Studio · "Take It Apart, Put It Back"
Course: Introduction to Computer Science — CS1 / Programming Fundamentals in Python (CSCI 1101) · Silver Oak University (fictional sample) · Prof. Okafor
Objective: Objective 7 — use the core string methods; explain immutability; write simple text algorithms · SLO A (write & run) + SLO B (trace & debug)
Worth 50 points · Coding Labs group = 15% of the grade · Coding Lab 11
Format: a hands-on programming studio worked in a free online Python environment — you'll (a) write a text-processing function, (b) trace string-method calls and predict their output, and (c) find and fix the immutability bug — and then catch the AI's mistake when it predicts a method's behavior.
This is the course's signature weekly component. Every instructional week has one Coding Lab. Everything runs in your browser — nothing to buy or install. The whole habit of this lab (and this course): don't guess what a method does — run it and read what Python actually returns.
Part 1 — The Big Picture
This week you learned the toolkit for working with text: the core string methods, the idea that strings are immutable (a method returns a new string and leaves the original alone), and your first text algorithms. This lab puts all three to work: you'll write a small text processor, trace method calls (predict what each returns, then run to check), and debug the classic "I called a method but nothing happened" bug. The one idea to keep in front of you: a method's result is useless unless you keep it — reassign (s = s.method()) or use it right away.
Your tools (both free, both in the browser):
- An online Python editor to write and run code: 🔗 https://www.online-python.com/ (or 🔗 https://www.programiz.com/python-programming/online-compiler)
- Python Tutor to watch immutability with your own eyes: 🔗 https://pythontutor.com/ — paste a snippet, click Visualize Execution, then step forward and watch a new string appear while the original stays put.
Part 2 — Setup (2 minutes)
- Open the online Python editor in a new tab.
- Delete any sample code so you have a blank editor.
- Type these three lines and press Run:
python s = "Hello" s.upper() print(s)
It printsHello, notHELLO. If that surprises you, good — that's immutability, and this whole lab is about it. You just saw a method return a value that got thrown away.
Part 3 — (a) Write: A Small Text Processor
Write each of these in the editor, run it, and paste your code and its output into your submission.
- Word counter. Write a function
word_count(sentence)that returns the number of words in a sentence. (Hint:.split()makes a list of the words;len(...)counts it.) Test it on"text processing is a useful skill"and write down what it returned. - Normalizer. Write a function
normalize(text)that returns the text with leading/trailing spaces removed and all lowercase. (Hint: chain.strip()then.lower().) Test it on" Mixed CASE input "and run it. - Censor. Write a function
censor(text, word)that returnstextwith every occurrence ofwordreplaced by"****". (Hint:.replace().) Test it oncensor("this is bad and bad", "bad")and run it.
Part 4 — (b) Trace: Predict, Then Run
You're working with one fixed string the whole table: s = "Hello, World". For each call below, first write your predicted output in the table (don't run it yet!). Then run each one in the editor and fill in the "Actual" column. Where your prediction and the actual output differ, that's the lesson.
Set this at the top of your editor once: s = "Hello, World"
| # | Program (with s = "Hello, World") |
Your prediction | Actual (after running) |
|---|---|---|---|
| 1 | print(s.upper()) |
______ | ______ |
| 2 | print(s.lower()) |
______ | ______ |
| 3 | print(s.split()) |
______ | ______ |
| 4 | print(s.count("l")) |
______ | ______ |
| 5 | print(s.find("W")) |
______ | ______ |
| 6 | print(s.replace("o", "0")) |
______ | ______ |
| 7 | print(s.startswith("Hello")) |
______ | ______ |
| 8 | s.upper() then on the next line print(s) |
______ | ______ |
Hint for #3:
.split()with no argument splits on whitespace — look carefully at what happens to the comma. Hint for #8: you already saw this in Setup. What issafter you calls.upper()without storing it?
Visualize one: paste #8 (s = "Hello, World", then s.upper(), then print(s)) into Python Tutor and step through it. Watch .upper() produce a new string that goes nowhere — and s never change.
Part 5 — (c) Find & Fix the Bug
Each program below is broken by the same kind of mistake — a string method was called but its result was never kept. For each one: run it, see what it actually prints, then write (i) why it's wrong, and (ii) the fixed program.
Bug A — this should greet in all caps (HELLO SAM) but doesn't:
name = "sam"
name.upper()
print("HELLO " + name)
Bug B — this should clean the entry down to answer: yes end but doesn't:
entry = " yes "
entry.strip()
print("answer:", entry, "end")
Part 6 — Analysis Questions
Answer in a sentence or two each:
1. In the trace table, which prediction did you get wrong (if any)? What did you learn from the gap?
2. Row #8 (s.upper() then print(s)) printed Hello, World, unchanged. In your own words, why — what does "strings are immutable" mean for a method's return value?
3. Row #3 (s.split()) — was the comma attached to a word or on its own? What does that tell you about how .split() with no separator decides where to cut?
4. Both Bug A and Bug B have the same underlying cause. In your own words, what is it, and what one habit fixes both?
5. Connect it: how is "don't guess what a method does — run it" visible in both the trace table and the two bugs this week?
Part 7 — AI-Critique Moment (required — this is the BYOAI step)
Now bring in your approved chatbot (Gemini, Claude, or ChatGPT) and be the programmer who checks its work. Chatbots are especially slippery about strings.
- Paste this to the chatbot: "In Python: (a) after
s = 'cat'and thens.replace('c', 'h'), what iss? (b) What does'a, b, c'.split()return? Give me the exact result of each." - Check every claim by running each one yourself in the editor:
- For (a): does it claimsis now'hat'? Run it — afters.replace('c', 'h')with no reassignment,sis still'cat'(strings are immutable; the new string was discarded). Chatbots often say the original changed.
- For (b): does it say'a, b, c'.split()returns['a', 'b', 'c']? Run it — with no separator,.split()cuts on whitespace only, so the commas stay attached: the real result is['a,', 'b,', 'c']. Chatbots routinely mis-split like this. - Write 2–3 sentences reporting what the AI got right and at least one thing you had to correct or verify by running it. If it happened to get everything right, say how you confirmed each one by running it — that's the skill.
The habit all term: the tool drafts, you run it and judge. On strings, a chatbot will confidently claim a method changed the original (it didn't) or mis-split on whitespace — catching it by running the code is the entire point of this course.
Part 8 — What to Submit
Submit a single document (or text entry) with: your Part 3 functions and their outputs; your completed Part 4 trace table (both columns); your Part 5 bug answers (why + the fix for each); your Part 6 answers; and your Part 7 AI-critique paragraph. Due Sunday, Nov 15, 11:59 p.m. (50 points).
Instructor answer key & model outputs — REMOVE BEFORE PUBLISHING TO STUDENTS
Execution gate: PASS — every output below was produced by actually running the code in Python. Students' Part 3 wording varies; grade those on "does it run and produce the right kind of output."
Part 3 (model):
1. def word_count(sentence): return len(sentence.split()) → word_count("text processing is a useful skill") returns 6 (run-verified). ✓
2. def normalize(text): return text.strip().lower() → normalize(" Mixed CASE input ") returns mixed case input (run-verified). ✓
3. def censor(text, word): return text.replace(word, "****") → censor("this is bad and bad", "bad") returns this is **** and **** (run-verified — .replace swaps both occurrences). ✓
Part 4 trace table (run-verified, with s = "Hello, World"):
| # | Program | Actual output |
|---|---|---|
| 1 | print(s.upper()) |
HELLO, WORLD |
| 2 | print(s.lower()) |
hello, world |
| 3 | print(s.split()) |
['Hello,', 'World'] |
| 4 | print(s.count("l")) |
3 |
| 5 | print(s.find("W")) |
7 |
| 6 | print(s.replace("o", "0")) |
Hell0, W0rld |
| 7 | print(s.startswith("Hello")) |
True |
| 8 | s.upper() then print(s) |
Hello, World |
(Note for #3: .split() with no separator keeps the comma on the first token → 'Hello,'. Note for #4: the lowercase l's are counted — there are 3 in "Hello, World". Note for #5: W is at index 7, counting the comma and space. Note for #8: immutability — s is unchanged.)
Part 5 bugs (run-verified):
- Bug A name.upper() discarded → prints HELLO sam. (i) name.upper() returns a new uppercase string but it's never stored; strings are immutable, so name stays "sam". (ii) Fix: name = name.upper() → then it prints HELLO SAM (run-verified).
- Bug B entry.strip() discarded → prints answer: yes end (spaces remain). (i) Same cause: .strip() returns a trimmed new string that's thrown away; entry is unchanged. (ii) Fix: entry = entry.strip() → then it prints answer: yes end (run-verified).
Part 6 (expected): (1) most commonly #3 (['Hello,', 'World'] — the comma surprise) or #8 (Hello, World, not HELLO, WORLD). (2) A string can't be changed, so a method builds and returns a new string; if you don't store that return value, the original is untouched — that's why row #8 prints the original. (3) The comma stayed attached to Hello, so .split() with no separator cuts only on whitespace, not on punctuation. (4) Same cause in both: the method's return value was never reassigned (or used); the one habit is reassign — name = name.upper(), entry = entry.strip(). (5) In both the table and the bugs, the result you expected from reading the code differs from what Python actually does until you run it — running it is what reveals the immutability behavior.
Part 7 (AI-critique): full credit for a specific catch — most commonly the AI claiming s becomes 'hat' after s.replace('c','h') (it stays 'cat'), or saying 'a, b, c'.split() returns ['a', 'b', 'c'] when it actually returns ['a,', 'b,', 'c']. Full credit also if the student verified each AI claim by running it.
Grading rubric — 50 points
| Criterion | Full | Partial | None |
|---|---|---|---|
| Part 3 — wrote & ran 3 functions (word_count, normalize, censor; code + output shown) (14) | 14 | 7–11 | 0–5 |
| Part 4 — trace table (predictions attempted + all 8 actual outputs correct from running) (14) | 14 | 7–11 | 0–5 |
| Part 5 — found & fixed both bugs (why + fix for each; both are the reassign bug) (12) | 12 | 6–10 | 0–4 |
Part 6 — analysis (immutability explained; the .split() comma point; the shared bug cause) (6) |
6 | 3–5 | 0–2 |
| Part 7 — AI-critique (names a specific string slip checked/corrected by running) (4) | 4 | 2 | 0–1 |
Quality gate (self-checked): every model output above (6, mixed case input, this is **** and ****, HELLO, WORLD, hello, world, ['Hello,', 'World'], 3, 7, Hell0, W0rld, True, Hello, World, HELLO SAM, answer: yes end, and the AI-critique results 'cat' and ['a,', 'b,', 'c']) was produced by actually running the code in Python — execution gate: PASS. No output is hand-traced. The lab grades the student's process (write → run → trace → debug), not a single fixed wording for the open-ended Part 3.
~ Prof. Okafor's edition · Fall 2026 · built with thecoursemaker.com