Pre-COSMOS Day 2, for Cluster 10: Robot Inventors, covered in depth. It covers the core types int, float, and str, plus bool, and checking a value with type(). It then explains that floats are approximate, covers // and %, points out that input() always returns text, and converts with int(), float(), and str() and with f-strings. From there it separates round() from the truncation that int() performs, covers the truthiness of bool(), and builds two calculators. The three high-confidence misconceptions each appear as a trap slide. Every snippet is runnable, and the outputs and error messages were copied verbatim from CPython 3.12.
Subject: Python · 79 slides · code lesson
Open the interactive version of this deck · Homework for this lesson
Objectives
Sensor readings, typed answers, and LED colors all reach your robot's program as data. By the end of this deck you can:
1. Name Python's core types - int, float, str (and bool) - and use type() to check any value.
2. Convert text to a number with int() / float(), and a number to text with str() or an f-string.
3. Explain why "3" + "4" is "34", and why "5" + 5 stops the program with an error.
4. Predict what int(3.9) gives - and know it chops the decimal, it does not round.
5. Use input() knowing it always hands you text, and split a number with // and %.
Concept
A distance sensor's reading and an LED's color both reach your program as data - but not the same KIND of data.
Numbers you can do math on. Text (a string) you can join together and display. Mix them up and Python stops you with an error.
So the first question about any value is always: what type is it? The type decides what you are allowed to do with it - add it, join it, or convert it first.
Counterexample
Discussion prompt
A distance sensor's reading and an LED's color both reach your program as data - but not the same KIND of data.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
Numbers you can do math on. Text (a string) you can join together and display. Mix them up and Python stops you with an error.
Concept
int - a whole number: 7, 0, -12. No decimal point. Python ints can be as huge as you like - no limit.
float - a number with a decimal point: 3.5, 0.0, -2.9.
str - text in quotes: "50", "red", "hello". The quotes are what make it text.
string (str) — A sequence of characters wrapped in quotes. "50" is the two characters 5 and 0 - it is text, not the number 50, even though it looks like a number to you.
Concept
bool holds just two values: True and False. It is what every yes/no question and every comparison produces - 5 > 3 is True.
A bool is secretly a number: True counts as 1 and False counts as 0. You will lean on this when a robot decides whether to act. We come back to it at the end.
Analogy
Discussion prompt
Explain A fourth type you'll meet: bool by analogy to something with no Python in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
A bool is secretly a number: True counts as 1 and False counts as 0. You will lean on this when a robot decides whether to act. We come back to it at the end.
Estimation
Predict first
When you are unsure what you are holding, ask Python directly:
Commit before you compute: what does Check the type with type() come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.
Correct: Read the output
Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Verified by execution - each line prints the class name of the value's type.
Worked example
When you are unsure what you are holding, ask Python directly:
print(type(7))
print(type(3.5))
print(type("hi"))
print(type(True))type(value) reports the kind of thing a value is
Why: It does not change the value - it just tells you the label. Run it any time a result surprises you.
Read the output
Why: Verified by execution - each line prints the class name of the value's type.
| expression | prints | the type |
|---|---|---|
| type(7) | <class 'int'> | int - whole number |
| type(3.5) | <class 'float'> | float - has a decimal |
| type("hi") | <class 'str'> | str - text in quotes |
| type(True) | <class 'bool'> | bool - True or False |
Comparison
Comparison matrix
From Check the type with type(): refill the prints column from what you know. The rest of the table is as it appeared.
| expression | prints | the type |
|---|---|---|
| type(7) | <class 'int'> | int - whole number |
| type(3.5) | <class 'float'> | float - has a decimal |
| type("hi") | <class 'str'> | str - text in quotes |
| type(True) | <class 'bool'> | bool - True or False |
Intuition
Picture each value sitting in a box with a label saying what kind of thing it is. The label decides which tools work on it.
5 wears an int label, so + means add. "5" wears a str label, so + means glue text together.
Same + symbol, different job - because the labels differ. That single idea explains almost every surprise in this deck.
Explain it
Discussion prompt
Explain Every value wears a label to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Picture each value sitting in a box with a label saying what kind of thing it is. The label decides which tools work on it.
Concept
The only difference is the dot. 3 is an int; 3.0 is a float. They look almost identical but Python treats them as different types.
One rule worth memorizing: dividing with / always gives a float, even when it divides evenly. 10 / 2 is 5.0, not 5.
Concept
Computers store decimals in binary, and most decimals can't be written exactly in binary - so floats carry tiny rounding errors.
floating-point — How computers store decimal numbers. Because the storage is approximate, 0.1 + 0.2 is not exactly 0.3. For money, work in whole cents (ints) to stay exact.
This is normal and happens in every language - not a bug in your code. Just don't expect two floats to be exactly equal.
Definition probe
Sort into buckets
Every line below is part of the definition of string (str) or of floating-point — one or the other, never both. Put each where it belongs.
Pattern
Predict first
The table runs: 10 / 2 | 5.0 | float · 10 / 4 | 2.5 | float
In Where floats sneak in, given the rows so far: what is the next one — the row where expression is 0.1 + 0.2?
Correct: 0.1 + 0.2 | 0.30000000000000004 | float (approximate!)
| expression | value | type |
|---|---|---|
| 10 / 2 | 5.0 | float |
| 10 / 4 | 2.5 | float |
| 0.1 + 0.2 | 0.30000000000000004 | float (approximate!) |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. The / operator produces a float every time, so the answer carries a decimal point even though it divides evenly.
Worked example
print(10 / 2)
print(10 / 4)
print(0.1 + 0.2)Line 1: 10 / 2 is 5.0, not 5
Why: The / operator produces a float every time, so the answer carries a decimal point even though it divides evenly.
Line 3: 0.1 + 0.2 is not exactly 0.3
Why: Verified by execution - the tiny tail of digits is the float approximation, not a mistake.
| expression | value | type |
|---|---|---|
| 10 / 2 | 5.0 | float |
| 10 / 4 | 2.5 | float |
| 0.1 + 0.2 | 0.30000000000000004 | float (approximate!) |
Trade off
Comparison matrix
From Where floats sneak in: every row here is a choice with a cost. Fill the value column, then say which row you would actually pick and what you give up for it.
| expression | value | type |
|---|---|---|
| 10 / 2 | 5.0 | float |
| 10 / 4 | 2.5 | float |
| 0.1 + 0.2 | 0.30000000000000004 | float (approximate!) |
Concept
// is floor division - it divides and throws away the remainder, giving a whole number: 7 // 2 is 3.
% is modulo - it gives only the remainder: 7 % 2 is 1. Together they split one number into a whole part and what's left over.
modulo (%) — The remainder after division. 125 % 60 is 5. Camp use: turn 125 total seconds into 2 minutes (125 // 60) and 5 seconds (125 % 60).
Ranking
Put in order
Put the moves of Splitting seconds into minutes into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. Floor division keeps only the whole number of 60s inside 125.
Worked example
total = 125
minutes = total // 60
seconds = total % 60
print(minutes, "min", seconds, "sec")Line 2: 125 // 60 is 2 - how many whole minutes fit
Why: Floor division keeps only the whole number of 60s inside 125.
Line 3: 125 % 60 is 5 - the leftover seconds
Why: Modulo returns what division left behind: 125 - (2 * 60) = 5.
Line 4: print joins everything with spaces
Why: Verified by execution: 2 min 5 sec. Note print() converts each piece to text for you - + would not.
| expression | value | meaning |
|---|---|---|
| 125 // 60 | 2 | whole 60s that fit |
| 125 % 60 | 5 | what is left over |
| print(...) | 2 min 5 sec | print space-joins, any type |
Error analysis
Annotate
Walk the callouts on Splitting seconds into minutes. Each one is a place this is easy to get subtly wrong.
Concept
Quotes turn anything into text. "50" is just the characters 5 and 0 - you cannot do math on it until you convert it.
This is exactly how a sensor reading or a typed-in answer arrives: as a string that looks like a number but isn't one yet.
Concept
input() pauses the program, lets the camper type, and gives back what they typed - always as a str, even if they type digits.
That is the whole reason this lesson matters: to do math on a typed-in or sensor value, you must convert it first with int() or float().
Worked example
age = input("How old are you? ")
print(type(age))input() gives back whatever was typed, as text
Why: No matter what the camper types, age is a str. type(age) confirms <class 'str'> every time.
Same result for digits, words, or decimals
Why: The quotes are invisible at the keyboard, but they are there. To compute with age you would write int(age).
| the camper types | age becomes | type(age) |
|---|---|---|
| 12 | "12" | str |
| hello | "hello" | str |
| 3.5 | "3.5" | str |
Invariant
Step through it
Step through Proof: input() returns a str one row at a time. One of these columns never changes — find it, and say why it cannot.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Goal: add the numbers 3 and 4.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: + between two strings concatenates - it glues the characters into "34".
Convert the text to numbers first, then add.
Why: + between two strings concatenates - it glues the characters into "34". It never adds them as numbers.
Trap
Goal: add the numbers 3 and 4.
print("3" + "4")Both sides are strings, so + joins them
Why: + between two strings concatenates - it glues the characters into "34". It never adds them as numbers.
| expression | you might expect | actual output |
|---|---|---|
| "3" + "4" | 7 | 34 |
Convert the text to numbers first, then add.
print(int("3") + int("4"))int() on each string makes them numbers
Why: int("3") is 3 and int("4") is 4, so now + means add. Real output: 7.
| expression | value | output |
|---|---|---|
| int("3") + int("4") | 7 | 7 |
Concept
int("50") reads the text "50" and hands back the number 50 - now you can do math with it.
float("3.5") does the same for decimals. It also accepts whole-number text: float("50") is 50.0.
One catch: int("3.5") fails - int() only accepts whole-number text. Use float() when the text has a decimal point.
Step zero
Discussion prompt
Converting a whole-number reading — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Line 1: reading is the TEXT "50"
Answer:
Worked example
A sensor sends "50" as text. Add one to it.
reading = "50"
n = int(reading) + 1
print(n)Line 1: reading is the TEXT "50"
Why: It looks like a number, but its type is str - you cannot add to it yet.
Line 2: int(reading) turns it into 50, then adds 1
Why: int("50") is 50, and 50 + 1 is 51. The result n is an int.
Trace each value
Why: Verified by execution: the program prints 51.
| step | expression | value | type |
|---|---|---|---|
| 1 | reading | "50" | str |
| 2 | int(reading) | 50 | int |
| 3 | int(reading) + 1 | 51 | int |
Blank canvas
Draw it
Draw what Converting a whole-number reading just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Estimation
Predict first
A temperature sensor sends "3.5". Double it.
Commit before you compute: what does Converting a decimal reading come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.
Correct: Trace each value
Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Verified by execution: 3.5 * 2 is 7.0, printed as 7.0 because a float stays a float.
Worked example
A temperature sensor sends "3.5". Double it.
reading = "3.5"
n = float(reading) * 2
print(n)Use float(), not int(), because the text has a decimal
Why: float("3.5") is 3.5. int("3.5") would crash - this is the conversion you reach for with decimals.
Trace each value
Why: Verified by execution: 3.5 * 2 is 7.0, printed as 7.0 because a float stays a float.
| step | expression | value | type |
|---|---|---|---|
| 1 | reading | "3.5" | str |
| 2 | float(reading) | 3.5 | float |
| 3 | float(reading) * 2 | 7.0 | float |
Anomaly
Predict first
A student writes this, and it looks reasonable:
You have the decimal text "3.5" and reach for int().
It is wrong. Say what breaks — and say it before you turn the page.
Correct: int() only parses whole-number text like "3".
Use float() for decimal text. If you then want a whole number, chop it with int() after.
Why: int() only parses whole-number text like "3". The ".5" makes it refuse, and the program stops.
Trap
You have the decimal text "3.5" and reach for int().
print(int("3.5"))int() rejects text that contains a decimal point
Why: int() only parses whole-number text like "3". The ".5" makes it refuse, and the program stops.
| expression | result |
|---|---|
| int("3.5") | ValueError: invalid literal for int() with base 10: '3.5' |
Use float() for decimal text. If you then want a whole number, chop it with int() after.
print(float("3.5"))
print(int(float("3.5")))float() reads the decimal text; int() can chop it afterward
Why: float("3.5") is 3.5. If you need a whole number, int(3.5) then gives 3. Real outputs: 3.5 and 3.
| expression | value | output |
|---|---|---|
| float("3.5") | 3.5 | 3.5 |
| int(float("3.5")) | 3 | 3 |
Break the constraint
Discussion prompt
The rule this trap just fixed:
Use float() for decimal text. If you then want a whole number, chop it with int() after.
Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?
Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.
Answer:
int() only parses whole-number text like "3". The ".5" makes it refuse, and the program stops.
Concept
str() goes the other way: str(50) gives the text "50". You need this to join a number into a message with +.
Reminder: print() already converts each piece for you, but + does not. So "Score: " + score fails unless you write str(score).
Ranking
Put in order
Put the moves of Building a message with str() into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. You cannot join an int directly onto "Score: " with + - the types do not match.
Worked example
score = 100
print("Score: " + str(score))Line 1: score is the number 100 (an int)
Why: You cannot join an int directly onto "Score: " with + - the types do not match.
Line 2: str(score) makes "100", then + joins
Why: str(100) is "100", and "Score: " + "100" is "Score: 100". Now both sides of + are text.
Trace each value
Why: Verified by execution: the program prints Score: 100.
| step | expression | value | type |
|---|---|---|---|
| 1 | score | 100 | int |
| 2 | str(score) | "100" | str |
| 3 | "Score: " + str(score) | "Score: 100" | str |
Concept
Joining with + str(...) works but gets clunky. An f-string lets you drop values straight into text: put f before the quotes and wrap each value in { }.
Inside the braces, Python converts the value to text for you automatically - no str() needed. f"Score: {score}" is the clean version of the last slide.
Explain it
Discussion prompt
Explain Next level: f-strings to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Joining with + str(...) works but gets clunky. An f-string lets you drop values straight into text: put f before the quotes and wrap each value in { }.
Fill the middle
Fill in the blanks
From The f-string version — one line has had its right-hand side removed. Put it back.
name = "Robo"
score = 100
print(f"___ scored ___")
Why: score is what everything below it consumes, so the wrong expression here fails later and somewhere else. {name} becomes Robo and {score} becomes 100 - automatically converted, no str() call.
Worked example
name = "Robo"
score = 100
print(f"{name} scored {score}")Each {...} is replaced by that value's text
Why: {name} becomes Robo and {score} becomes 100 - automatically converted, no str() call.
Trace the substitution
Why: Verified by execution: the program prints Robo scored 100. Same result as +, far easier to read.
| piece | fills in with |
|---|---|
| {name} | Robo |
| {score} | 100 |
| whole f-string | "Robo scored 100" |
Comparison
Comparison matrix
From The f-string version: refill the fills in with column from what you know. The rest of the table is as it appeared.
| piece | fills in with |
|---|---|
| {name} | Robo |
| {score} | 100 |
| whole f-string | "Robo scored 100" |
Anomaly
Predict first
A student writes this, and it looks reasonable:
A sensor reading "5" plus the number 5.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: One side is text, the other a number.
Decide what you want - math, or joined text - and convert one side to match.
Why: One side is text, the other a number. Python refuses to guess and stops. (5 + "5" fails the same way, with the message worded the other direction.)
Trap
A sensor reading "5" plus the number 5.
print("5" + 5)You cannot + a str and an int together
Why: One side is text, the other a number. Python refuses to guess and stops. (5 + "5" fails the same way, with the message worded the other direction.)
| expression | result |
|---|---|
| "5" + 5 | TypeError: can only concatenate str (not "int") to str |
Decide what you want - math, or joined text - and convert one side to match.
print(int("5") + 5)
print("5" + str(5))Make both sides the same type first
Why: For math, convert the text to a number: int("5") + 5 is 10. For text, convert the number: "5" + str(5) is "55". Real outputs: 10 and 55.
| expression | value | output |
|---|---|---|
| int("5") + 5 | 10 | 10 |
| "5" + str(5) | "55" | 55 |
Concept
Calling int() on a float removes the decimal part - it does not round. int(3.9) is 3, and int(3.2) is also 3. Both just drop everything after the dot.
truncate — To cut off the decimal part and keep only the whole-number part. int(3.9) truncates to 3 - it ignores how close 3.9 is to 4.
If you actually want the nearest whole number, that is a different tool: round().
Matching
Match the pairs
Match each term to the definition this lesson gave it — not the one you would guess from the word.
Why: These are the working definitions of string (str), floating-point, modulo (%), truncate as Data Types & Conversion uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.
Worked example
print(int(3.9))
print(int(3.2))
print(int(-2.9))Each call drops the decimal and keeps the whole part
Why: 3.9 and 3.2 both become 3. The size of the decimal never matters - int() chops it off entirely.
Negatives chop toward zero
Why: Verified by execution: int(-2.9) is -2, not -3. int() moves toward zero, it does not round down.
| expression | value | what happened |
|---|---|---|
| int(3.9) | 3 | decimal chopped off |
| int(3.2) | 3 | decimal chopped off |
| int(-2.9) | -2 | chopped toward zero, not down |
Anomaly
Predict first
A student writes this, and it looks reasonable:
You want to round 3.9 to the nearest whole number.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Because 3.9 is almost 4, people expect 4.
To round to the nearest whole number, use round().
Why: Because 3.9 is almost 4, people expect 4. But int() only chops the decimal, leaving 3.
Trap
You want to round 3.9 to the nearest whole number.
print(int(3.9))int() truncates - it ignores how close 3.9 is to 4
Why: Because 3.9 is almost 4, people expect 4. But int() only chops the decimal, leaving 3.
| expression | you might expect | actual |
|---|---|---|
| int(3.9) | 4 | 3 |
To round to the nearest whole number, use round().
print(round(3.9))round() picks the nearest whole number
Why: round(3.9) is 4 because 3.9 is closer to 4 than to 3. Use int() to chop, round() to round - pick the one you mean.
| expression | value | output |
|---|---|---|
| round(3.9) | 4 | 4 |
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
bool is secretly a number: True counts as 1 and False counts as 0. You will lean on this when a robot decides whether to act. We come back to it at the end.; Picture each value sitting in a box with a label saying what kind of thing it is. The label decides which tools work on it."3.5" and reach for int().Concept
round(x) gives the nearest whole number. round(x, n) keeps n decimal places: round(3.14159, 2) is 3.14.
One surprise: an exact half rounds to the nearest even number, not always up. round(2.5) is 2, but round(3.5) is 4. This keeps large sums fair - just don't be shocked by it.
Analogy
Discussion prompt
Explain round(): to the nearest - mostly by analogy to something with no Python in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
round(x) gives the nearest whole number. round(x, n) keeps n decimal places: round(3.14159, 2) is 3.14.
Worked example
print(round(3.14159, 2))
print(round(3.5))
print(round(2.5))Second argument = how many decimals to keep
Why: round(3.14159, 2) keeps two places: 3.14.
Halves round to the nearest even number
Why: Verified by execution: round(3.5) is 4 (even), round(2.5) is 2 (even). Not a bug - it is the rule.
| expression | value | note |
|---|---|---|
| round(3.14159, 2) | 3.14 | keep 2 decimal places |
| round(3.5) | 4 | nearest even |
| round(2.5) | 2 | nearest even (not 3!) |
Blank canvas
Draw it
Draw what round() in action just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Concept
bool(x) answers is this value truthy? Zero, an empty string, and nothing-at-all are falsy; everything else is truthy.
The classic trap: bool("0") is True. The string "0" is not empty - it has one character - so it counts as truthy, even though the number 0 is falsy.
Counterexample
Discussion prompt
bool(x) answers is this value truthy? Zero, an empty string, and nothing-at-all are falsy; everything else is truthy.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
The classic trap: bool("0") is True. The string "0" is not empty - it has one character - so it counts as truthy, even though the number 0 is falsy.
Pattern
Predict first
The table runs: bool(0) | False | zero is the only falsy number · bool(5) | True | any non-zero number is truthy · bool("") | False | an empty string is falsy
In Truthy and falsy values, given the rows so far: what is the next one — the row where expression is bool("0")?
Correct: bool("0") | True | non-empty string - even "0"
| expression | value | why |
|---|---|---|
| bool(0) | False | zero is the only falsy number |
| bool(5) | True | any non-zero number is truthy |
| bool("") | False | an empty string is falsy |
| bool("0") | True | non-empty string - even "0" |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. bool(0) is False; any non-zero number, like 5, is True.
Worked example
print(bool(0))
print(bool(5))
print(bool(""))
print(bool("0"))Numbers: only 0 is falsy
Why: bool(0) is False; any non-zero number, like 5, is True.
Strings: only the empty string is falsy
Why: Verified by execution: bool("") is False, but bool("0") is True because the string holds a character.
| expression | value | why |
|---|---|---|
| bool(0) | False | zero is the only falsy number |
| bool(5) | True | any non-zero number is truthy |
| bool("") | False | an empty string is falsy |
| bool("0") | True | non-empty string - even "0" |
Discrimination
Sort into buckets
Sort these by value, from memory, without looking back at Truthy and falsy values. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Step zero
Discussion prompt
Build it: the area calculator — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.
Hint: It starts with: Lines 1-2: the measurements arrive as TEXT
Answer:
Worked example
Two measurements arrive as text. Compute a rectangle's area and display it - the full text -> number -> text round trip.
length = "12"
width = "8"
area = int(length) * int(width)
print("Area = " + str(area))Lines 1-2: the measurements arrive as TEXT
Why: length is "12" and width is "8" - strings, even though they look like numbers. You cannot multiply them yet.
Line 3: convert both to int, then multiply
Why: int("12") is 12, int("8") is 8, and 12 * 8 is 96. area is now an int.
Line 4: convert the result back to text to display it
Why: str(96) is "96", and "Area = " + "96" is "Area = 96". Both sides of + are text again.
Trace every line
Why: Verified by execution: prints Area = 96. This is the table to write on paper before you run anything.
| line | variable | value | type |
|---|---|---|---|
| 1 | length | "12" | str |
| 2 | width | "8" | str |
| 3 | area | 96 | int |
| 4 | (printed) | Area = 96 | str |
Pattern
Step through it
Step through Build it: the area calculator one row at a time. What is driving the change, and what would the row after the last one be?
Ranking
Put in order
Put the moves of Build it bigger: temperature converter into the order they have to happen.
Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. If the camper types 100, input() returns "100"; int("100") makes it 100.
Worked example
Now with real input and an f-string. Read a Celsius temperature, convert to Fahrenheit, and display it cleanly.
celsius = int(input("Temp in C? "))
fahrenheit = celsius * 9/5 + 32
print(f"{celsius}C is {fahrenheit}F")Line 1: input() gives text, int() wraps it into a number
Why: If the camper types 100, input() returns "100"; int("100") makes it 100. The int() is what lets the next line do math.
Line 2: the formula - and / makes it a float
Why: 100 * 9 / 5 + 32 is 212.0. Because / is used, fahrenheit is a float (note the .0).
Line 3: an f-string drops both values into text
Why: Verified by execution (typing 100): prints 100C is 212.0F. No str() calls needed - the braces convert for you.
| line | variable | value | type |
|---|---|---|---|
| 1 | celsius | 100 | int (int() wrapped input) |
| 2 | fahrenheit | 212.0 | float (/ made it a float) |
| 3 | (printed) | 100C is 212.0F | str (f-string built it) |
Error analysis
Annotate
Walk the callouts on Build it bigger: temperature converter. Each one is a place this is easy to get subtly wrong.
Pattern
1. When in doubt, check the type with type(value)
Why: If it prints <class 'str'>, you have text and must convert before doing any math. Anything from input() is always a str.
2. Text to number: int() for whole numbers, float() for decimals
Why: int("50") is 50; float("3.5") is 3.5. int() rejects text that has a decimal point.
3. Number to text: str(), or just use an f-string
Why: "Score: " + str(score) works; f"Score: {score}" is the cleaner next-level way and converts for you.
4. Never + a str and a number together
Why: "5" + 5 is a TypeError. Convert one side so both are the same type first.
5. int() chops, round() rounds
Why: int(3.9) is 3; round(3.9) is 4. And remember floats are approximate - don't expect them to be exact.
Real world
Discussion prompt
Outside this lesson: where does Data Types & Conversion actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of The conversion recipe is doing the work in it.
Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.
Answer:
Pre-COSMOS Day 2 (Cluster 10: Robot Inventors), in depth. The core types int, float, str (plus bool); checking with type(); floats are approximate; // and %; input() always returns text; converting with int()/float()/str() and f-strings; round() vs int() truncation; bool() truthiness; and two build-it calculators.
Check
Decide the type of each side of the + first, then pick your answer.
print("3" + "4")| expression | output |
|---|---|
| "3" + "4" | ? |
Check your understanding
What does this program display?
Answer: B
Why: Both operands are strings, so + concatenates them into the text "34"; print shows it without the quotes. To add them as numbers you would convert first: int("3") + int("4") is 7. Verified by execution: this prints 34.
Check
Trace it line by line - remember what int() does to a decimal.
x = int(3.9)
print(x + 1)| step | expression | value |
|---|---|---|
| 1 | int(3.9) | ? |
| 2 | x + 1 | ? |
Check your understanding
What does this program print?
Answer: A
Why: int(3.9) truncates - it chops the decimal to 3, it does not round to 4. Then 3 + 1 is 4. Verified by execution: this prints 4.
Trade off
Comparison matrix
From Check yourself: chop or round?: every row here is a choice with a cost. Fill the value column, then say which row you would actually pick and what you give up for it.
| step | expression | value |
|---|---|---|
| 1 | int(3.9) | ? |
| 2 | x + 1 | ? |
Check
The camper runs this and types 12 at the prompt.
answer = input("How many? ")
print(type(answer))| typed | answer | type(answer) |
|---|---|---|
| 12 | ? | ? |
Check your understanding
What does type(answer) print?
Answer: B
Why: input() always returns a str, even when the camper types digits. answer is the text "12", so type(answer) is <class 'str'>. To get a number you must wrap it: int(input(...)). Verified by execution.
Elimination
Eliminate the wrong options
What does this program print, line by line?
3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.
Survives elimination: A
Why: // is floor division: 7 // 2 throws away the remainder and gives the int 3. / is true division: 7 / 2 gives the float 3.5. Verified by execution: the output is 3 then 3.5.
Check
These two look similar but give different types. Trace both.
print(7 // 2)
print(7 / 2)| expression | value |
|---|---|
| 7 // 2 | ? |
| 7 / 2 | ? |
Check your understanding
What does this program print, line by line?
Answer: A
Why: // is floor division: 7 // 2 throws away the remainder and gives the int 3. / is true division: 7 / 2 gives the float 3.5. Verified by execution: the output is 3 then 3.5.
Comparison
Comparison matrix
From Check yourself: // vs /: refill the value column from what you know. The rest of the table is as it appeared.
| expression | value |
|---|---|
| 7 // 2 | ? |
| 7 / 2 | ? |
Check
Falsy means zero or empty. Look carefully at the quotes.
print(bool("0"))| expression | output |
|---|---|
| bool("0") | ? |
Check your understanding
What does this print?
Answer: A
Why: "0" is a string with one character, so it is non-empty and therefore truthy: bool("0") is True. Only the empty string "" is falsy. The number 0 is falsy, but the text "0" is not the number 0. Verified by execution.
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — The conversion recipe · Why types matter at camp · The three core types · A fourth type you'll meet: bool · Every value wears a label. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
Core types - int, float, str, bool - and type() tells you which you have. int() / float() turn text into numbers; str() and f-strings turn numbers into text.
| You have | You want | Use |
|---|---|---|
| "50" (text) | the number 50 | int("50") |
| "3.5" (text) | the number 3.5 | float("3.5") |
| 50 (number) | it inside a message | str(50) or f"...{50}..." |
| text from input() | a number to compute with | int(input()) / float(input()) |
| 3.9 (float) | the whole number 3 | int(3.9) - chops |
| 3.9 (float) | the nearest whole, 4 | round(3.9) |
And the two that trip everyone: "3" + "4" joins into "34", and "5" + 5 is an error. When a value surprises you, check its type and convert. Now go build the calculator.
Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.