This lesson turns the prompt into a calculator, meets the int, float and str types through the type function, and explains the two surprises Python plants on purpose: why division gives 42.0 and why the caret does not mean exponentiation.
Subject: Python · 65 slides · code lesson
Open the interactive version of this deck
Title
Python · Chapter 1 — The way of the program
§1.4-1.7, pp. 3-6
Objectives
Five things, each one you can check yourself at an interpreter prompt.
type() to ask Python which one a value has.Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 3-6 — the pages these objectives are drawn from
Warm-up
You met the prompt last lesson. Now put arithmetic into it, and commit to a prediction first.
Discussion prompt
Write down, without running anything, what you think Python displays for each of these three lines: 40 + 2, then 84 / 2, then 6 * 7. Be exact about every character, including any decimal point.
Hint: Two of the three will be exactly what you expect. One of them will not.
Answer:
40 + 2 gives 42 and 6 * 7 gives 42, both exactly as written.
84 / 2 gives 42.0 — with a decimal point and a zero. Almost nobody predicts that the first time, and it is not a rounding artefact or a display quirk.
The book raises this deliberately and then says I will explain in the next section. The explanation is types, and it is the real subject of this lesson.
Concept
Python does not just hold values. It holds values that know what kind of thing they are, and what an operator does depends on the kinds of thing it was given. That single fact explains the decimal point, explains why quoted numbers behave oddly, and will keep explaining things for the rest of the book.
type — A category of values. The type of a value determines what operations are possible on it and what those operations mean.
The book puts it as: a value is one of the basic things a program works with, like a letter or a number, and these values belong to different types. The word Python prints for a type is class, used in the sense of a category.
Figure (svg): Three columns of example values labelled int, float and str, showing whole numbers, numbers with decimal points, and quoted text
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 4-4
Section
Section 1
Concept
Python provides operators, which are special symbols that represent computations like addition and multiplication. Five of them cover everything in this chapter.
operator — A special symbol that represents a simple computation, such as addition, multiplication or exponentiation.
>>> 40 + 2
42
>>> 43 - 1
42
>>> 6 * 7
42| Operator | What it does | Example from the book |
|---|---|---|
| + | addition | 40 + 2 gives 42 |
| - | subtraction | 43 - 1 gives 42 |
| * | multiplication | 6 * 7 gives 42 |
The book gets to 42 three different ways on purpose. The value is the same; the computations are not, and it is the computations you are learning to write.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 3-3
Picture it
This shape is worth fixing in your mind now, because every operator in the book has it.
Figure (svg): A diagram showing two input values entering an operator box and a single result value leaving it
Because the result is itself a value, operators chain: 40 + 2 - 1 is the result of the first operator fed into the second.
Worked example
Predict the result before advancing. There is only one rule you need, and you already have it.
>>> 6 * 7 - 2 * 5
32| Sub-expression | Why it runs when it does | What is left |
|---|---|---|
| 6 * 7 | multiplication runs first | 42 - 2 * 5 |
| 2 * 5 | the other multiplication runs | 42 - 10 |
| 42 - 10 | subtraction runs last | 32 |
Find the multiplications.
Why: Multiplication is done before subtraction, which is the same convention as ordinary arithmetic. The next lesson states the full rule.
Replace each multiplication with its result.
Why: 42 minus 10. This is the same move you would make on paper, and it is exactly what Python does internally.
Run what is left.
Why: One subtraction, one result.
Figure (svg): The state of the program after each line of Worked example chaining operators, drawn as a ladder with one rung per traced line
32. The two multiplications happen first, leaving 42 - 10, and the subtraction produces 32.
Verify: Add parentheses where you believe the grouping is, and check that the answer does not change.
Why: Typing (6 * 7) - (2 * 5) gives 32 as well. If the two forms had disagreed, your reading of the grouping was wrong — and this is the cheapest possible way to test a reading of an expression.
Prediction
You have been told it is not exponentiation. Commit to what it is.
Predict first
Python is asked for 6 caret 2. It displays 4. What is the caret doing?
Correct: A bitwise operation called XOR, which works on the binary digits of the two numbers.
Why: Six in binary is 110 and two is 010. XOR compares them digit by digit and produces a 1 wherever exactly one of the two inputs has a 1, giving 100, which is 4. The book does not cover bitwise operators and neither does this course — what matters here is that the caret is a real operator doing a real job, which is why it produces a confident answer rather than an error.
Worked example
The operator for raising to a power is two stars, not the caret. Read it carefully.
>>> 6**2 + 6
42| Sub-expression | Why it runs when it does | What is left |
|---|---|---|
| 6**2 | exponentiation runs first | 36 + 6 |
| 36 + 6 | addition runs second | 42 |
| result | the interpreter displays it | 42 |
Read the double star as raised to the power of.
Why: The operator double-star performs exponentiation; that is, it raises a number to a power.
Do the exponentiation before the addition.
Why: Exponentiation binds more tightly than addition, again matching ordinary arithmetic.
Finish the addition.
Why: 36 plus 6 is 42, which is the book's answer and a third route to the same number.
Figure (svg): A three-rung ladder showing six double-star two plus six reducing to thirty-six plus six and then to forty-two
42. Six squared is 36, and adding six gives 42.
Verify: Compute the same thing with multiplication instead and compare.
Why: Typing 6 * 6 + 6 also gives 42. Exponentiation by a small whole number is repeated multiplication, so the two must agree — and when they do not, the reading of the exponent is where to look.
Trap
In some other languages the caret means raised to the power of. A student who knows one of those writes six caret two, expecting 36.
Assume the symbol carries its meaning across languages
Why: The caret means exponentiation in many calculators, in several programming languages, and in most typed mathematics.
Python displays 4. Not 36, and not an error — a perfectly confident, completely different answer.
In Python the caret is a bitwise operator called XOR, and it does something else entirely.
Use the double star for exponentiation
Why: That is Python's symbol for it, and it is unambiguous.
Treat a plausible but wrong answer as the most dangerous kind
Why: An error message would have stopped you. A wrong number will not, and it will travel downstream into everything that used it.
The book flags this precisely because it does not produce an error. If you are not familiar with bitwise operators, the result will surprise you — and a surprise you do not notice is a bug.
Matching
Five symbols, five jobs. One of them is the one people get wrong.
Match the pairs
Why: Four of these five match what you would guess from ordinary arithmetic, which is why the fifth is worth singling out: exponentiation is TWO stars, and a single star is multiplication. The symbol that is missing from this list on purpose is the caret, which looks like it should be here and is not.
Reverse engineer
You know the two inputs and the result. Name the operator.
Fill in the blanks
6 *** 7 -> 42
6 ** 2 -> 36
6 ^** 2 -> 4
Why: The first is multiplication, six sevens being forty-two. The second must be exponentiation, because six times two is only twelve and six squared is thirty-six. The third is the caret — the only one of the three that produces a number you cannot reach by any ordinary arithmetic on 6 and 2, which is itself the clue that something other than arithmetic is happening.
Estimation
Estimate before computing. The point is the shape of the growth, not the digits.
Predict first
Roughly how many digits does 2 raised to the power 100 have?
Correct: About 30 digits.
Why: Every ten doublings multiply a number by roughly a thousand, which adds about three digits. A hundred doublings is ten such groups, so about thirty digits — the exact answer is 31. This is worth estimating once because exponentiation is the first operator in the book whose results leave the range you can hold in your head, and Python will happily compute it exactly, with no overflow and no rounding, which not every language does.
Section
Section 2
Concept
The division operator behaves like the others in every respect except one: its result always carries a decimal point, even when the division comes out exactly.
>>> 84 / 2
42.0| Stage | What happens | Result |
|---|---|---|
| 84 / 2 | the division is computed exactly | the value forty-two |
| result type | division always produces a float | 42.0, not 42 |
| display | a float is displayed with its decimal point | 42.0 |
You might wonder why the result is 42.0 instead of 42. It is not that Python failed to notice the division was exact. It is that the division operator is defined to produce a float — a number with a decimal point — regardless of the inputs, so that 84 / 2 and 85 / 2 behave the same way as each other.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 3-4
Picture it
42 and 42.0 are the same quantity. They are not the same value, because they are not the same type.
Figure (svg): Two columns contrasting the integer forty-two with the float forty-two point zero, showing how each is produced and displayed
For now this is a curiosity. In chapter 5 it becomes a decision you make deliberately, when the book introduces an operator that divides and keeps the result whole.
Worked example
Four expressions. Decide for each whether the result will be displayed with a decimal point.
>>> 10 + 5
15
>>> 10 / 5
2.0
>>> 10 * 5
50
>>> 10 / 4
2.5| Expression | Why | Result and type |
|---|---|---|
| 10 + 5 | addition of two ints | 15 — an int |
| 10 / 5 | division always makes a float | 2.0 — a float |
| 10 * 5 | multiplication of two ints | 50 — an int |
| 10 / 4 | division, and not exact either | 2.5 — a float |
Look for the division operator, and nothing else.
Why: It is the only one of the five that changes the type of the result. The others give back the kind of number they were given.
Note that exactness is irrelevant.
Why: 10 / 5 divides evenly and still produces 2.0. The decimal point comes from the operator, not from the remainder.
Note that 10 / 4 needed the decimal point.
Why: This is why the rule is what it is: if division sometimes produced an int, the type of the answer would depend on the values, and you could not predict it by reading the code.
Figure (svg): The state of the program after each line of Worked example predicting which operations give a decimal point, drawn as a ladder with one rung per traced line
Only the two divisions produce a decimal point, and both of them do, whether or not the division was exact. Addition and multiplication of whole numbers give whole numbers.
Verify: Ask what would go wrong if division returned an int when the division was exact.
Why: The type of 10 / n would then depend on the value of n, so you could not tell by reading the program what kind of value you were holding. Consistency is bought at the price of a slightly surprising 2.0, and it is worth the price.
Prediction
One rule decides all four. Apply it before you read them individually.
Predict first
Which of these results is displayed with a decimal point?
Correct: Both 9 / 3 and 9 / 2, because both are divisions and division always produces a float.
Why: The tempting answer is the one about coming out evenly, because that is how a person would decide when a decimal point is needed. Python does not decide per-value; the operator decides. 9 / 3 gives 3.0 and 9 / 2 gives 4.5, and the decimal point in the first is there for exactly the same reason as the decimal point in the second.
Worked example
One float in an expression is enough to change the type of everything downstream. Predict the result.
>>> 84 / 2 + 8
50.0| Sub-expression | What happens | What is left |
|---|---|---|
| 84 / 2 | division produces a float | 42.0 + 8 |
| 42.0 + 8 | a float plus an int | 50.0 — still a float |
| display | the float keeps its decimal point | 50.0 |
Run the division first.
Why: It binds more tightly than addition, so 42.0 is what the addition receives.
Add an int to a float.
Why: Python converts the int to a float and adds, because a float can represent everything an int can but not the other way round.
Read the type of the final result.
Why: Still a float, so still displayed with a decimal point — the division at the start has coloured the whole expression.
Figure (svg): A three-rung ladder showing eighty-four divided by two plus eight reducing through forty-two point zero plus eight to fifty point zero
50.0, with a decimal point, because the division early in the expression produced a float and the addition preserved it.
Verify: Replace the division with a multiplication that gives the same number and compare.
Why: 42 * 1 + 8 gives 58 without a decimal point when written with ints; the shape of the expression is the same and only the type differs. Changing one operator and watching the decimal point appear or vanish is direct evidence that the type travels through the expression.
Trap
A student sees 42.0 where they expected 42 and concludes that Python has rounded, or lost precision, or is showing an approximate answer.
Read the decimal point as a warning about accuracy
Why: In science and engineering notation, extra decimal places usually do carry information about precision.
From there it is a short step to distrusting the result, or to adding code that tries to fix a problem that does not exist.
The decimal point is a statement about TYPE, not about accuracy.
Read 42.0 as the float forty-two
Why: It is exactly forty-two. Not 41.999, not rounded, not approximate.
Ask what produced it, if you want to know why it is a float
Why: A division did, and division always does. That is the entire explanation.
Floats CAN be approximate — that is a real issue and the book returns to it — but the decimal point in 42.0 is not evidence of it. It is evidence that a division happened.
Discrimination
Sort by the type of the result, not by the size of the number.
Sort into buckets
For each expression, will Python display a whole number or a number with a decimal point?
Socratic
The design could have gone the other way. Argue against it.
Discussion prompt
Suppose Python's division returned an int whenever the division came out exactly, and a float otherwise. Describe one concrete situation in which that would make a program harder to reason about.
Hint: Think about a division where you do not know the numbers in advance.
Answer:
Imagine a program that divides a total by a count entered by the user. Under the proposed rule, the TYPE of the result would depend on numbers that do not exist until the program runs.
You could no longer look at the line and say what kind of value it produces — you would have to know the data. Any code downstream that cared about the type would work on Tuesday and fail on Wednesday.
Python chooses predictability: the operator determines the type, always. The cost is one surprising 42.0 on your first day; the benefit is that you can reason about types by reading.
Edge cases
Division has one input it cannot handle. Predict what Python does about it.
Discussion prompt
You type 1 / 0 at the prompt. Python does not display a number. What do you think it displays instead, and why is that better than displaying something like infinity?
Hint: Think about what you would want to happen if this were buried in the middle of a long program.
Answer:
Python reports an error: ZeroDivisionError, with the message division by zero. Nothing is computed and nothing is displayed as a result.
It is better than an infinity value because it stops the program at the point where the impossible thing happened. An infinity would travel silently through the rest of the computation and produce a nonsensical final answer with no indication of where it went wrong.
This is the first error you have met that is about the VALUES rather than about the writing. The next section is about the other kind, and telling them apart is most of what Appendix A is for.
Section
Section 3
Concept
A value is one of the basic things a program works with, like a letter or a number. The values met so far belong to three different types, and if you are not sure what type a value has, the interpreter can tell you.
>>> type(2)
<class 'int'>
>>> type(42.0)
<class 'float'>
>>> type('Hello, World!')
<class 'str'>| Value | What it looks like | Its type |
|---|---|---|
| 2 | a whole number | int |
| 42.0 | a number with a decimal point | float |
| 'Hello, World!' | text in quotation marks | str |
Integers belong to the type int, floating-point numbers to float, and strings to str — so-called because the letters it contains are strung together. In the results, the word class is used in the sense of a category; a type is a category of values.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 4-4
Picture it
It takes a value and hands back the name of its category. It never modifies anything.
Figure (svg): A diagram showing a value entering the type function and the name of its category coming out
This is the first diagnostic tool of the course, and it stays useful for the whole book. When something behaves strangely, asking what type it actually is resolves a surprising fraction of the mystery.
Worked example
The output has a shape. Learn to read past the punctuation to the word that matters.
>>> type(42.0)
<class 'float'>| Part of the output | What it is | What to do with it |
|---|---|---|
| <class | Python's word for a category | ignore it for now |
| 'float' | the name of the type | this is the answer |
| > | the closing bracket of the display form | ignore it too |
Find the quoted word in the middle.
Why: That is the name of the type, and it is the only part of the output that changes from value to value.
Read class as category.
Why: The book is explicit about this: the word class is used in the sense of a category, and a type is a category of values. Its other meaning arrives in chapter 15.
Ignore the angle brackets.
Why: They are how Python displays this kind of object. They carry no information about your value.
Figure (svg): The state of the program after each line of Worked example reading what type reports, drawn as a ladder with one rung per traced line
The type is float. Everything else in the output is Python's standard way of displaying a type, and it looks the same whatever value you ask about.
Verify: Ask about two values you are certain of and compare the shapes of the answers.
Why: type(2) gives the same output with int in the quotes, and type('a') gives the same output with str. Three answers with identical structure and one word different confirms which word is the content.
Definition probe
Look at how each one is written, not at what it means.
Sort into buckets
Which of the three types does each value belong to?
Worked example
Go back to the 42.0 from earlier and settle it with evidence rather than argument.
>>> type(84 / 2)
<class 'float'>
>>> type(84 // 2)
<class 'int'>| Expression | Which operator | Type of the result |
|---|---|---|
| 84 / 2 | ordinary division | float |
| 84 // 2 | a second division operator, met properly in chapter 5 | int |
| comparison | same numbers, same answer, different type | the operator decides |
Wrap the whole expression in type() rather than just a value.
Why: type() takes any value, and the result of an expression is a value. This lets you ask about a computation rather than a literal.
Read the first answer.
Why: float — which confirms that the division, not the numbers, produced the decimal point.
Compare with the double-slash operator.
Why: Same two numbers, same mathematical answer, and an int comes back. Chapter 5 introduces this operator properly; here it is evidence.
Figure (svg): A two-row state diagram showing eighty-four divided by two producing a float and eighty-four double-slash two producing an int
Division with a single slash produces a float and division with a double slash produces an int, from identical inputs. The type of a result is determined by the operator, which is exactly what the earlier section claimed.
Verify: Check that the two operators agree about the value even though they disagree about the type.
Why: Both give forty-two. If they had disagreed about the value as well, the double slash would be doing something other than dividing — so this check separates the type claim from a value claim, and only the type claim is in question.
Error analysis
A student wrote these four lines in their notes after the lesson. Two are wrong. Mark them.
Annotate
The next section is entirely about the fourth line, because that mistake causes more first-month confusion than any other in this chapter.
Prediction
type() takes a value. An expression produces a value. Put them together.
Predict first
What does Python display for type(3 + 4)?
Correct: It displays the class int, because 3 + 4 is evaluated first and the resulting value, 7, is an int.
Why: Everything inside the parentheses is worked out before type() is asked anything at all. By the time type() sees anything, the addition is finished and there is a single value, 7, to report on. This is the same rule as the print statement from the last lesson — what is inside the parentheses is evaluated first — and it is worth noticing that it is the same rule, because it will be the same rule every time.
Translation
Each of these is how a value is WRITTEN. Match it to what Python will report.
Match the pairs
Why: Three of these are about how a literal value is written, and the fourth is about what an operator produces. Between them they cover every value you have met so far. Notice that all four rules are decidable by looking — you never have to know what a value means to know its type, which is what makes types useful for reasoning about a program before you run it.
Explain it to yourself
The word is confusing on first meeting and the book addresses it in one sentence.
Discussion prompt
Python reports the type of 2 as class int, not as type int. Explain what the word class is doing there, and why it is safe to ignore its other meaning for now.
Hint: The book gives you the sense in which the word is being used.
Answer:
The book says it directly: the word class is used in the sense of a category, and a type is a category of values. Read class int as the int category and nothing is lost.
The word has a second, much more specific meaning in Python, which arrives in chapter 15 when you start defining categories of your own. It is genuinely the same idea — a class is a category — which is why the language reuses the word.
Ignoring it for now is safe because nothing you do in the next fourteen chapters depends on the distinction. Being told that the word will come back, however, is worth something: it means the confusion is temporary rather than a gap in your understanding.
Section
Section 4
Concept
They look like numbers, but they are in quotation marks like strings. And that settles it: they are strings. Quotation marks are not decoration and they are not optional punctuation — they are what makes a value a str.
>>> type('2')
<class 'str'>
>>> type('42.0')
<class 'str'>
>>> type(2)
<class 'int'>| Value as written | Quoted? | Type |
|---|---|---|
| '2' | quoted | str |
| '42.0' | quoted | str |
| 2 | not quoted | int |
This matters more than it looks. In chapter 5 the input function will hand you text that looks exactly like a number, and every operation you try on it will behave like text until you convert it. Knowing that the quotation marks decide is what makes that debuggable.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 4-4
Picture it
Same characters, two values, and no amount of squinting will make them the same.
Figure (svg): Two columns contrasting the unquoted number two with the quoted string two, listing what each can do
That last row is the one to remember: the same operator does different work depending on the types it is given. This is the deepest idea in the lesson and it comes back constantly.
Worked example
Type a large number the way you would write it on paper, and watch what Python does with it.
>>> 1,000,000
(1, 0, 0)| What you typed | How Python reads it | Result |
|---|---|---|
| 1,000,000 | Python reads the commas as separators | three values, not one |
| 1 000 000 | each group is read as its own number | 1, then 0, then 0 |
| (1, 0, 0) | the three are displayed as a sequence | not the number one million |
Notice that this is not an error.
Why: It is legal, and Python does something confident and completely unlike what you meant. That makes it more dangerous than an error, not less.
Work out what the commas did.
Why: Python interprets the input as a comma-separated sequence of integers. The commas separated three values rather than grouping digits.
Read the three values.
Why: The first group is 1. The second and third are 000, which is just zero. Hence 1, 0 and 0.
Figure (svg): The typed characters one comma zero zero zero comma zero zero zero drawn as boxes, split into three groups by the commas
Python displays (1, 0, 0) — three separate numbers, not one million. Commas between groups of digits are not legal in a Python integer; they are read as separators between values.
Verify: Type the number without commas and compare.
Why: 1000000 displays as 1000000, a single value. The difference between the two is three commas, which is a strong reminder that in a formal language punctuation is never decorative.
Two truths and a lie
Two of these are true. Keep the false one.
Eliminate the wrong options
Rule out the two true statements and keep the lie.
Survives elimination: C
Why: C is false, and it is false on purpose — this is a language design decision rather than an oversight. If Python silently converted, then '2' + 2 would give 4 and '2' + '2' would give 4 as well, and you could never join two pieces of text that happened to look numeric. Instead Python refuses and reports a TypeError, which tells you exactly where the assumption went wrong.
Worked example
Predict what each of these two lines displays. They differ only by quotation marks.
>>> 2 + 2
4
>>> '2' + '2'
'22'| Expression | Types involved | Result |
|---|---|---|
| 2 + 2 | two ints, so plus means addition | 4 |
| '2' + '2' | two strs, so plus means joining | '22' |
| comparison | identical operator, different types | different meaning |
Identify the types before deciding what the operator does.
Why: This is the correct order of reasoning and it is the reverse of what most beginners do.
Apply plus to two ints.
Why: It adds them. Four.
Apply plus to two strs.
Why: It joins them end to end, giving the two-character text 22. Nothing was added; the characters were strung together, which is what str is named for.
Figure (svg): The state of the program after each line of Worked example text that looks like arithmetic, drawn as a ladder with one rung per traced line
The first line gives the number 4. The second gives the text 22 — two characters side by side, not the number twenty-two. The operator is the same; the types are not.
Verify: Ask type() about both results.
Why: The first is an int, the second is a str. The two results are not merely different numbers, they are different kinds of thing — and a str '22' cannot be used in arithmetic without being converted first.
Trap
A student writes a number in quotes because it looked tidier, or because they copied it from somewhere that had quotes, and then tries to do arithmetic with it.
Treat quotation marks as presentation
Why: In English, quoting a number changes nothing about the number. It is a reasonable assumption to bring.
Then '10' + 5 fails with a TypeError, or worse, '10' + '5' silently gives '105' and the program carries on with a wrong value.
Quotation marks change what the value IS, not how it looks.
Decide deliberately whether you want a quantity or some characters
Why: A house number you will never do arithmetic on is reasonably a str. A price is not.
Use type() the moment something behaves oddly
Why: It takes three seconds and it answers this question definitively.
This is not a rare edge case. From chapter 5 onward, everything the user types arrives as a str, including things that are obviously numbers, and converting it is a step you must remember.
Prediction
You know what plus does to strings. Reason your way to what star does.
Predict first
Python is given a string of one character, '3', multiplied by the number 4. What happens?
Correct: It gives '3333' — the string repeated four times.
Why: If plus joins strings end to end, then multiplying a string by a whole number repeats it, which is what repeated joining means. Python defines it exactly that way. This is worth meeting now because it is another confident, non-error answer to something you might have typed by mistake, and because it shows the pattern: operators are not restricted to numbers, they are given a sensible meaning for each type they are offered.
Missing information
Sometimes you genuinely cannot tell from the value alone, and that is the point.
Discussion prompt
You are handed the value 90210 and asked whether it should be an int or a str in your program. What do you need to know before you can answer, and what would swing it each way?
Hint: Ask what operations the program will perform on it.
Answer:
You need to know what the program will DO with it. Types are about which operations make sense, so the operations decide.
If it is a postal code, str is right: you will never add two postal codes, and leading zeros matter — as an int, 09210 would silently become 9210.
If it is a population count, int is right: you will compare it, add to it, and average it. The value looks identical either way, which is exactly why the decision has to come from the use and not from the appearance.
Notation
This is the error you get when the types do not fit the operator. Read it line by line.
Annotate
Nearly every error message in Python has this shape: a name that gives the category, then a sentence naming the specific things involved. Reading both halves is a skill worth building now.
Section
Section 5
Concept
Natural languages are the languages people speak — they were not designed, they evolved. Formal languages are designed by people for specific applications, and programming languages are formal languages designed to express computations.
formal language — A language designed by people for a specific application, with strict syntax rules governing the structure of statements.
The practical consequence is the one the book puts last and means hardest: the details matter. Small errors in spelling and punctuation, which you can get away with in a natural language, can make a big difference in a formal language.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 4-6
Picture it
Syntax rules come in two flavours, and knowing which one you broke tells you where to look.
Figure (svg): Two columns showing token errors and structure errors, with a mathematical and a chemical example of each
When Python reports a syntax error, one of these two rules is what you broke. Asking which narrows the search enormously.
Worked example
Parsing is figuring out the structure. You do it subconsciously in English; here you do it deliberately.
>>> print('total:', 3 * 4)
total: 12| Token | What it is | Role |
|---|---|---|
| a token: the name of a function | structure | |
| ( ... ) | a token pair: this is a call | structure |
| 'total:' | a token: a str | content |
| , | a token: separates the two things given to print | structure |
| 3 * 4 | three tokens forming one expression | evaluated to 12 |
Break the line into tokens.
Why: Tokens are the basic elements of the language — names, numbers, operators, punctuation. This is the first thing Python does, and doing it yourself is what reading code means.
Work out how the tokens combine.
Why: The parentheses group everything given to print; the comma separates two separate things; the star combines the two numbers around it.
Evaluate from the inside out.
Why: 3 * 4 becomes 12 before print sees anything, exactly as in every earlier example.
Figure (svg): The state of the program after each line of Worked example parsing a line the way Python does, drawn as a ladder with one rung per traced line
It displays total: 12. The comma separated two values, so print displayed both with a space between them, and the multiplication was evaluated before print received it.
Verify: Check the space in the output against the source.
Why: There is no space after the colon inside the quotes, yet the output has one. That space came from the comma between the two values, which tells you the comma is doing structural work rather than being displayed — the token analysis predicted this and the output confirms it.
Sorting
Every one of these is broken. The question is which rule it breaks.
Sort into buckets
Sort each broken line by the kind of syntax rule it violates.
Worked example
Two broken lines. Diagnose which of the two kinds of rule each one breaks.
print('hi' $ 'there')
print('hi' 'there' +)| Line | What is wrong | Which kind of rule |
|---|---|---|
| line 1 | the dollar sign is not a Python token at all | token error |
| line 2 | every symbol is legal, but plus has nothing on its right | structure error |
| both | reported as SyntaxError, before anything runs | no output |
Check line 1 symbol by symbol.
Why: The dollar sign is not a legal token in Python. This is the direct analogue of the book's example, where the dollar is not a legal token in mathematics either.
Check line 2 symbol by symbol.
Why: Every symbol on it is legal Python. The strings are fine, the plus is a real operator, the parentheses are matched.
Check line 2's structure.
Why: The plus is an operator that needs a value on each side, and there is nothing to its right before the parenthesis closes. Legal tokens, illegal arrangement.
Figure (svg): A traceback panel showing a syntax error with the offending line, a caret pointing at the position, and the error name
Line 1 breaks a token rule: it contains a symbol that is not part of the language. Line 2 breaks a structure rule: every symbol is legal, but they are not combined in a legal way.
Verify: Ask whether fixing the arrangement could rescue either line.
Why: Line 2 can be rescued by rearranging alone — put a value after the plus. Line 1 cannot be rescued by any rearrangement, because the offending symbol has no legal position anywhere. That asymmetry is precisely what distinguishes the two kinds of error.
Trap
A student reads a program the way they read English: left to right, top to bottom, at speed, filling in anything unclear from context.
Apply reading habits built for a redundant, ambiguous language
Why: English tolerates skimming because it repeats itself. Missing a word rarely loses the meaning.
Formal languages are more dense than natural languages, so it takes longer to read them — and they are not redundant, so a missed character is a missed meaning.
Learn to parse the program in your head: identify the tokens and interpret the structure.
Read for tokens first, not for meaning
Why: Which symbols are here? Are they all legal? Is every opener paired with its closer?
Then read for structure, which is often not left to right
Why: Innermost parentheses evaluate first, so the reading order and the running order differ.
It is slower, and it is supposed to be. The book says it directly: it is not always best to read from top to bottom, left to right.
Analogy
Match each property of natural language to the example that shows it.
Match the pairs
Why: Each of the three is something English does that Python cannot. The telescope sentence has several readings and people pick one from context; Python is designed so that no statement has more than one meaning. The verb ending repeats information for safety; Python states everything once. And the idiom means something unrelated to its words; Python means exactly what it says. The third is the one that trips beginners hardest, because a variable named total does not add anything up — the name is for you, and the machine is entirely literal.
Real world
You have been using several without calling them that.
Discussion prompt
Name a formal language you already use outside programming, and give one example of a rule it enforces that English would not. Then say what happens when you break that rule.
Hint: The book mentions two: mathematical notation and chemical formulae.
Answer:
Mathematical notation is the clearest. It enforces that an operator has something on both sides, which is why 3 + / 3 is meaningless even though every symbol in it is legal.
Chemical formulae enforce that the subscript follows the element name and that the element abbreviation exists. H2O is well-formed; 2Zz breaks both rules at once.
What happens when you break the rule is the interesting part: a human reader usually still guesses your meaning, and that is exactly what a compiler or interpreter will not do. The strictness is not pedantry — it is the price of having exactly one meaning.
Explain it to yourself
The book's first debugging section is mostly about how it feels, which is unusual and deliberate.
Discussion prompt
The book suggests thinking of the computer as an employee with strengths like speed and precision, and weaknesses like a lack of empathy and an inability to grasp the big picture. Explain how that framing would change what you do when you hit an error you do not understand.
Hint: What do you do with an employee who is precise but has no idea what you meant?
Answer:
You stop expecting it to infer your intention, and start checking what you actually told it. The error is a report about the instructions, not a judgement about you.
You also stop arguing with it. If a precise, literal reader says the syntax is wrong at line 1, the syntax is wrong at line 1, and the productive question is which token or which structure — not whether it is mistaken.
The book is explicit that programming, and especially debugging, sometimes brings out strong emotions, and that preparing for them helps. That is a genuinely practical claim: a student who expects frustration works through it, and a student who reads it as evidence of not being clever enough stops.
Comparison
Fill the blanks from memory. This table is the whole of chapter 1's type content.
Comparison matrix
| Type | How it is written | What plus does to two of them |
|---|---|---|
| int | a whole number, no decimal point, no quotes | adds them: 2 + 2 gives 4 |
| float | a number with a decimal point | adds them: 2.0 + 2.0 gives 4.0 |
| str | anything at all inside quotation marks | joins them: '2' + '2' gives '22' |
The right-hand column is the punchline: one operator, three meanings, chosen by the types it is given.
Pattern
This is the diagnostic loop for every unexpected value in the rest of the book, and it starts working today.
Step 2 is the one people skip, and it is the one that answers the question. Asking about the INPUTS as well as the result is what separates a diagnosis from a guess.
Python documentation — An Informal Introduction to Python An Informal Introduction to Python
Check
One rule decides this, and it is not about whether the division is exact.
>>> 20 / 4
5.0| Expression | What happens | Result |
|---|---|---|
| 20 / 4 | a division | always produces a float |
| 5.0 | displayed with its decimal point | the value five, as a float |
| type | asking type() confirms it | float |
Check your understanding
Why does 20 / 4 display as 5.0 rather than 5?
Answer: B
Why: The type of the result is determined by the operator, not by the values. Division with a single slash is defined to produce a float every time, which is what makes its behaviour predictable by reading rather than by knowing the numbers. Five point zero is exactly five; the decimal point reports the type.
Check
Look at how the values are written before deciding what the operator does.
>>> '10' + '5'
'105'| Value | Type and why | What plus does |
|---|---|---|
| '10' | quoted, so a str | text |
| '5' | quoted, so a str | text |
| + | given two strs, so it joins them | '105' |
Check your understanding
Why does this produce '105' rather than 15?
Answer: B
Why: The quotation marks make both values strings, and the plus operator joins strings rather than adding them. The result is a two-part piece of text, '105', which is a str and not the number one hundred and five. This is the central idea of the lesson: an operator's meaning depends on the types it is given.
Check
Both lines are broken. Only one of them contains a symbol Python does not have.
Check your understanding
Which of these breaks a TOKEN rule rather than a structure rule?
Answer: B
Why: A token rule is broken when the line contains a symbol that is not part of the language at all. The pound sign is not a Python token, so no rearrangement of that line could ever make it legal. The other three are made entirely of legal symbols combined in illegal ways, which is what a structure error is.
Real world
Types are not a Python idea. You have been distinguishing them your whole life without a word for it.
Discussion prompt
Find a place outside programming where the same characters mean two different things depending on what kind of thing they are — and where treating one as the other causes a real problem. Spreadsheets, phone numbers and dates are all good hunting grounds.
Hint: What happens to a phone number beginning with a zero when a spreadsheet decides it is a number?
Answer:
Spreadsheets are the everyday version of this exact bug. Type a phone number starting with zero and the leading zero vanishes, because the spreadsheet decided the value was a quantity rather than a label.
Dates are worse: 03/04 is the third of April or the fourth of March depending on a setting you cannot see in the cell. Same characters, two values, and no way to tell by looking.
Both are the '42' problem. The fix in both cases is the same as in Python: say explicitly what kind of thing the value is, rather than letting its appearance decide.
Commit first
Answer, then rate your confidence. A confident wrong answer here is worth more than a hesitant right one.
Predict first
What does Python display for type('42.0')?
Correct: The class str, because the value is in quotation marks — what is inside them makes no difference to the type.
Why: Everything inside quotation marks is a str, without exception and without inspection. Python does not look inside to see whether the contents happen to look numeric, which is precisely why '42.0' and 'Hello' have the same type. If you were tempted by float, you were reading the value for meaning rather than for how it was written — and that is the habit this whole lesson exists to break.
Explain it
One minute, no jargon they have not met. The constraint is the exercise.
Discussion prompt
A friend types 84 / 2 into Python, gets 42.0, and asks whether Python is broken. Explain what happened, why it is not a bug, and what they could type to confirm your explanation.
Hint: The confirming command is the most valuable part of your answer.
Answer:
A good answer says: the decimal point means the value is a float, division always makes a float, and 42.0 is exactly forty-two rather than an approximation.
A very good answer ends with something they can type: type(84 / 2) reports float, and type(84 // 2) reports int from the same numbers. That turns your claim into something they can check without trusting you.
Offering a way to check is worth more than the explanation itself. It is also the habit that makes you good at debugging, because it means your beliefs about a program are always one command away from being tested.
Exit ticket
One honest answer. It decides what the next lesson opens with.
Predict first
Which of these is still least solid for you?
Correct: Whichever you picked is the right answer — this one is for you, not for a mark.
Why: These four have very different half-lives. The operators are memory and settle within a week. The float rule is a single fact that stops being surprising once you have said it out loud twice. The number-versus-string distinction will keep biting until chapter 5 forces you to convert user input, at which point it becomes second nature. And reading error messages improves for as long as you program — Appendix A exists entirely for it.
Connect it up
One page, no code, from memory.
Draw it
Draw a diagram with three boxes for the three types and arrows between them for the operations that move between the boxes. Label each arrow with what causes that move — a division, a pair of quotation marks, a conversion. Then mark the one arrow that Python will NOT take automatically, and write one sentence saying why refusing to take it is a good design decision.
Recap
Three pages of a book, one calculator, and the idea that will explain more bugs than any other in this course.
type(), which is the first diagnostic tool of the course.| Surprise | The one-line explanation |
|---|---|
| 84 / 2 gives 42.0 | Division always produces a float. The decimal point is about type, not accuracy. |
| 6 caret 2 gives 4 | The caret is bitwise XOR in Python. Exponentiation is the double star. |
| 1,000,000 gives (1, 0, 0) | Commas separate values. They never group digits. |
| '2' + '2' gives '22' | Plus joins strings. The types decide what an operator means. |
| type(2) says class int | Class here means category. Its other meaning waits until chapter 15. |
Chapter 2 gives values names, which turns a calculator into something that can remember — and introduces the first errors that are your fault rather than Python's.
Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 3-6 — everything on these slides traces back here
Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.