1b Arithmetic, Values, Types, and Your First Errors

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

What this lesson covers

The lesson, slide by slide

1. Lesson 1b Arithmetic, Values, Types, and Your First Errors

Title

Python · Chapter 1 — The way of the program

§1.4-1.7, pp. 3-6

2. By the end of this lesson you can

Objectives

Five things, each one you can check yourself at an interpreter prompt.

Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 3-6 — the pages these objectives are drawn from

3. Before we start: what do you expect Python to say?

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.

4. The one idea behind this lesson: every value has a type

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

And between them: float, the numbers with a decimal point, such as 42.0 and 3.5.

Think Python, 2nd edition — Allen B. Downey §1.4-1.7, pp. 4-4

5. Operators: the symbols that compute

Section

Section 1

6. The five arithmetic operators

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
OperatorWhat it doesExample from the book
+addition40 + 2 gives 42
-subtraction43 - 1 gives 42
*multiplication6 * 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

7. Picture it: an operator takes two values and produces one

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

Two in, one out. The result is a value like any other, so it can go into another operator.

Because the result is itself a value, operators chain: 40 + 2 - 1 is the result of the first operator fed into the second.

8. Worked example: chaining operators

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-expressionWhy it runs when it doesWhat is left
6 * 7multiplication runs first42 - 2 * 5
2 * 5the other multiplication runs42 - 10
42 - 10subtraction runs last32

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

The whole run at once: each drop is one line of the program.

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.

9. Predict: what does the caret actually do?

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?

  • Subtracting, so it computes 6 minus 2
  • A bitwise operation called XOR, which works on the binary digits
  • Rounding 6 down to the nearest multiple of 2
  • Reporting an error code rather than a value

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.

10. Worked example: exponentiation with the double star

Worked example

The operator for raising to a power is two stars, not the caret. Read it carefully.

>>> 6**2 + 6
42
Sub-expressionWhy it runs when it doesWhat is left
6**2exponentiation runs first36 + 6
36 + 6addition runs second42
resultthe interpreter displays it42

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

One operator per rung, in the order Python runs them.

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.

11. Trap: using the caret for exponentiation

Trap

The 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.

The fix

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.

12. Match each operator to what it computes

Matching

Five symbols, five jobs. One of them is the one people get wrong.

Match the pairs

  • a. +
  • b. -
  • c. *
  • d. /
  • e. **
  • r1. addition
  • r2. subtraction
  • r3. multiplication
  • r4. division
  • r5. exponentiation

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.

13. Reverse engineer: which operator was used?

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.

14. Estimate: how big does exponentiation get?

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?

  • About 10
  • About 30
  • About 100
  • About 300

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.

15. Division, and the decimal point that appears from nowhere

Section

Section 2

16. Why 84 / 2 is 42.0 and not 42

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
StageWhat happensResult
84 / 2the division is computed exactlythe value forty-two
result typedivision always produces a float42.0, not 42
displaya float is displayed with its decimal point42.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

17. Picture it: same value, two types

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

The same point on the number line, reached two ways, held two ways.

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.

18. Worked example: predicting which operations give a decimal point

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
ExpressionWhyResult and type
10 + 5addition of two ints15 — an int
10 / 5division always makes a float2.0 — a float
10 * 5multiplication of two ints50 — an int
10 / 4division, and not exact either2.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

The whole run at once: each drop is one line of the program.

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.

19. Predict: which of these displays a decimal point?

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?

  • Only 9 / 3, because it is the only division
  • Only 9 / 2, because it is the only one that does not come out evenly
  • Both 9 / 3 and 9 / 2, because both are divisions
  • None of them, because all the inputs are whole numbers

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.

20. Worked example: a float that spreads

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-expressionWhat happensWhat is left
84 / 2division produces a float42.0 + 8
42.0 + 8a float plus an int50.0 — still a float
displaythe float keeps its decimal point50.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

The decimal point enters at the first rung and never leaves.

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.

21. Trap: reading 42.0 as an approximation

Trap

The 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 fix

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.

22. Discriminate: int result or float result?

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?

a whole number, no decimal point
7 + 3; 2 ** 10; 5 * 5
a decimal point appears
7 / 1; 100 / 10; 1 / 3
int
Addition, multiplication and exponentiation of whole numbers give whole numbers back. None of these expressions contains a division.
float
Every one of these contains the division operator, and division always produces a float — including 7 / 1, which is a division by one, and 100 / 10, which comes out exactly.

23. Think it through: why not make division smart?

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.

24. Push the boundary: what about dividing by zero?

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.

25. Values, types, and asking Python which is which

Section

Section 3

26. Three types, and the function that reports them

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'>
ValueWhat it looks likeIts type
2a whole numberint
42.0a number with a decimal pointfloat
'Hello, World!'text in quotation marksstr

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

27. Picture it: type() is a question you can always ask

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

Available at any prompt, on any value, at any time. Use it whenever you are unsure.

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.

28. Worked example: reading what type() reports

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 outputWhat it isWhat to do with it
<classPython's word for a categoryignore it for now
'float'the name of the typethis is the answer
>the closing bracket of the display formignore 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 whole run at once: each drop is one line of the program.

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.

29. Definition probe: sort these values by type

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?

int
17; 0
float
17.0; 3.14
str
'17'; 'Hello'
int
Written as whole numbers with no decimal point and no quotation marks. Zero is an int like any other whole number.
float
Written with a decimal point. It does not matter that 17.0 happens to be a whole quantity — the decimal point is what makes it a float.
str
Written inside quotation marks. What is inside them is irrelevant to the type: '17' is a str exactly as much as 'Hello' is.

30. Worked example: using type() to explain a surprise

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'>
ExpressionWhich operatorType of the result
84 / 2ordinary divisionfloat
84 // 2a second division operator, met properly in chapter 5int
comparisonsame numbers, same answer, different typethe 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

The operator, not the values, decides the type of the result.

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.

31. Error analysis: a student's notes on types

Error analysis

A student wrote these four lines in their notes after the lesson. Two are wrong. Mark them.

Annotate

  • Line 1 is right. A whole number written without a decimal point is an int.
  • Line 2 is right. A number written with a decimal point is a float.
  • Line 3 is wrong, and the reason given is the problem. 42 and 42.0 are the same NUMBER but not the same VALUE, because they are not the same type. type(42) is int.
  • Line 4 is wrong for a different reason: the quotation marks. Anything in quotation marks is a str, whatever it looks like inside them. type('42') is str.
  • The two mistakes are the two halves of the same misunderstanding — deciding a type by looking at what a value MEANS rather than at how it is written. Python decides by how it is written, every time.

The next section is entirely about the fourth line, because that mistake causes more first-month confusion than any other in this chapter.

32. Predict: what does type() say about an expression?

Prediction

type() takes a value. An expression produces a value. Put them together.

Predict first

What does Python display for type(3 + 4)?

  • <class 'int'>, because 3 + 4 is 7 and 7 is an int
  • An error, because type() needs a single value and not an expression
  • <class 'str'>, because the expression was written as text
  • <class 'float'>, because arithmetic always produces floats

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.

33. Translate: from what you see to what it is

Translation

Each of these is how a value is WRITTEN. Match it to what Python will report.

Match the pairs

  • a. a number with no decimal point and no quotes
  • b. a number with a decimal point
  • c. anything at all inside quotation marks
  • d. the result of any division with a single slash
  • r1. int
  • r2. float
  • r3. str
  • r4. float, whatever the inputs were

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.

34. Explain it yourself: why does the interpreter say *class*?

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.

35. Numbers that are not numbers: strings, and the comma trap

Section

Section 4

36. What about values like '2' and '42.0'?

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 writtenQuoted?Type
'2'quotedstr
'42.0'quotedstr
2not quotedint

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

37. Picture it: the quotes are a wrapper, and the wrapper is the type

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

The plus operator exists for both, and means something different for each.

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.

38. Worked example: the comma trap

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 typedHow Python reads itResult
1,000,000Python reads the commas as separatorsthree values, not one
1 000 000each group is read as its own number1, then 0, then 0
(1, 0, 0)the three are displayed as a sequencenot 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

The highlighted commas are separators. Python sees 1, then 0, then 0.

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.

39. Two truths and a lie: quotation marks

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.

  • A. '2' and 2 have different types
  • B. The plus operator means something different for strs than for ints
  • C. Python converts '2' to a number automatically when you use it in arithmetic

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.

40. Worked example: text that looks like arithmetic

Worked example

Predict what each of these two lines displays. They differ only by quotation marks.

>>> 2 + 2
4
>>> '2' + '2'
'22'
ExpressionTypes involvedResult
2 + 2two ints, so plus means addition4
'2' + '2'two strs, so plus means joining'22'
comparisonidentical operator, different typesdifferent 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 whole run at once: each drop is one line of the program.

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.

41. Trap: assuming quotation marks are harmless

Trap

The 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.

The fix

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.

42. Predict: what does '3' * 4 do?

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?

  • It gives 12, converting the string to a number
  • It gives '3333', repeating the string four times
  • It gives an error, because you cannot multiply text
  • It gives '34', joining them together

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.

43. Missing information: is this a number or not?

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.

44. Decode the notation: reading a TypeError

Notation

This is the error you get when the types do not fit the operator. Read it line by line.

Annotate

  • The first line says a traceback follows, and that the most recent call is listed last. With one line of code there is only one entry.
  • The second line locates the problem: standard input, line 1. When you are working at the prompt this is always where it is.
  • The third line is the one that matters, and it has two halves: the error's NAME and its explanation.
  • TypeError is the name, and it tells you the category: something was the wrong type for what you asked. Not a typo, not a missing value — a type mismatch.
  • The message names both types: it can concatenate a str to a str, but you gave it an int. Concatenate is the technical word for joining end to end, which is what plus does to strings.
  • So the fix follows from the message: convert the int to a str, or convert the str to an int, depending on whether you meant to join or to add.

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.

45. Formal languages, and why the details matter so much

Section

Section 5

46. What kind of language Python is

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

47. Picture it: two kinds of syntax rule

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

Tokens are the basic elements; structure is the way they are combined.

When Python reports a syntax error, one of these two rules is what you broke. Asking which narrows the search enormously.

48. Worked example: parsing a line the way Python does

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
TokenWhat it isRole
printa token: the name of a functionstructure
( ... )a token pair: this is a callstructure
'total:'a token: a strcontent
,a token: separates the two things given to printstructure
3 * 4three tokens forming one expressionevaluated 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

The whole run at once: each drop is one line of the program.

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.

49. Sort: token error or structure error?

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.

token rule: an illegal symbol
2 £ 3 — a pound sign used as an operator
structure rule: legal symbols, illegal arrangement
print('hi' @ 'there') — an at-sign between two strings; 3 + / 3 — two operators in a row; print('hi' — an opening parenthesis never closed
token
The pound sign is not a token in Python at all. No rearrangement can rescue a line containing it, because there is no legal position for a symbol the language does not have.
struct
Every symbol in these is legal Python — the at-sign really is an operator, the slash really is division, the parenthesis really does open a group. What is wrong is how they are arranged: operators without operands, or an opener with no closer.

50. Worked example: a token error and a structure error

Worked example

Two broken lines. Diagnose which of the two kinds of rule each one breaks.

print('hi' $ 'there')
print('hi' 'there' +)
LineWhat is wrongWhich kind of rule
line 1the dollar sign is not a Python token at alltoken error
line 2every symbol is legal, but plus has nothing on its rightstructure error
bothreported as SyntaxError, before anything runsno 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.

51. Trap: reading a program the way you read a paragraph

Trap

The 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.

The fix

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.

52. Analogical pivot: the three differences, in examples

Analogy

Match each property of natural language to the example that shows it.

Match the pairs

  • am. ambiguity
  • re. redundancy
  • li. literalness
  • r1. The penny dropped means somebody understood, and involves no penny
  • r2. He goes and they go — the verb repeats information the pronoun already gave
  • r3. I saw a man on a hill with a telescope — who has the telescope?

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.

53. Where else do you already use a formal language?

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.

54. Explain it yourself: debugging as a skill and a mood

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.

55. Compare: the three types side by side

Comparison

Fill the blanks from memory. This table is the whole of chapter 1's type content.

Comparison matrix

TypeHow it is writtenWhat plus does to two of them
inta whole number, no decimal point, no quotesadds them: 2 + 2 gives 4
floata number with a decimal pointadds them: 2.0 + 2.0 gives 4.0
stranything at all inside quotation marksjoins them: '2' + '2' gives '22'

The right-hand column is the punchline: one operator, three meanings, chosen by the types it is given.

56. The procedure: when a result surprises you

Pattern

This is the diagnostic loop for every unexpected value in the rest of the book, and it starts working today.

  1. Read the result exactly, character by character. A decimal point, a pair of quotation marks or a set of parentheses is information, not noise.
  2. Ask type() about the result, and about each input that produced it.
  3. If the types are not what you expected, find the operator or the literal that produced them.
  4. If the types ARE what you expected, ask what that operator means for those types — it may not mean what it means for numbers.
  5. Only then decide whether to convert a value, change an operator, or accept that the answer was right all along.

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

57. Check yourself 1 of 3: the decimal point

Check

One rule decides this, and it is not about whether the division is exact.

>>> 20 / 4
5.0
ExpressionWhat happensResult
20 / 4a divisionalways produces a float
5.0displayed with its decimal pointthe value five, as a float
typeasking type() confirms itfloat

Check your understanding

Why does 20 / 4 display as 5.0 rather than 5?

  • A. Because Python rounds all division results to one decimal place
  • B. Because the division operator always produces a float, whatever the inputs (correct)
  • C. Because 20 and 4 are too large to be held as whole numbers
  • D. Because the result is not exact, so Python shows the approximation

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.

Why A tempts people
There is no rounding here. 20 / 3 gives 6.666666666666667, with many more than one decimal place, so no rounding-to-one-place rule can be operating.
Why C tempts people
Size is not involved. Python holds whole numbers of arbitrary size happily, and 20 and 4 are not remotely large.
Why D tempts people
The result IS exact — five, precisely. This is the misreading the section warned about: the decimal point is a statement about type, not about accuracy.

58. Check yourself 2 of 3: quoted numbers

Check

Look at how the values are written before deciding what the operator does.

>>> '10' + '5'
'105'
ValueType and whyWhat plus does
'10'quoted, so a strtext
'5'quoted, so a strtext
+given two strs, so it joins them'105'

Check your understanding

Why does this produce '105' rather than 15?

  • A. Because Python adds the digits from left to right and runs out of room
  • B. Because both values are strings, and plus joins strings end to end (correct)
  • C. Because 10 and 5 are being treated as a sequence, like 1,000,000 was
  • D. Because the quotation marks make Python treat the plus as a comma

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.

Why A tempts people
No addition of any kind takes place, so there is nothing to run out of room for. Python is joining characters, not summing digits.
Why C tempts people
The comma trap is a different mechanism entirely — there, commas separated three values. Here there is one operator and two values, and the operator did its string job.
Why D tempts people
The plus is still a plus. What changed is the types it was handed, not the operator's identity.

59. Check yourself 3 of 3: token or structure?

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?

  • A. print(3 + )
  • B. print(3 £ 4) (correct)
  • C. print('hi'
  • D. print(3 3)

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.

Why A tempts people
Every symbol here is legal Python. The problem is that the plus operator has nothing on its right, which is an arrangement problem — a structure error.
Why C tempts people
The parenthesis and the string are both legal. What is wrong is that an opener was never closed, which is again about arrangement rather than about the symbols themselves.
Why D tempts people
Two numbers are both perfectly legal tokens. Placing them side by side with no operator between them is the illegal part, so this too is a structure error.

60. Where this shows up outside this course

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.

61. Confidence wager: commit before you check

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')?

  • The class float, because 42.0 has a decimal point
  • The class str, because the value is in quotation marks
  • The class int, because it is a number
  • An error, because the quotes make it ambiguous

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.

62. Explain it to someone else

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.

63. Exit ticket

Exit ticket

One honest answer. It decides what the next lesson opens with.

Predict first

Which of these is still least solid for you?

  • The operators, especially the double star and the caret
  • Why division produces a float even when it comes out evenly
  • Telling a number from a string that looks like a number
  • Reading an error message and telling a token error from a structure error

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.

64. Synthesis: draw the map of this lesson

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.

65. What you can do now

Recap

Three pages of a book, one calculator, and the idea that will explain more bugs than any other in this course.

SurpriseThe one-line explanation
84 / 2 gives 42.0Division always produces a float. The decimal point is about type, not accuracy.
6 caret 2 gives 4The 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 intClass 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

Sources

  1. Think Python, 2nd edition — Allen B. Downey — Allen B. Downey, Think Python: How to Think Like a Computer Scientist, 2nd edition (Green Tea Press, 2015), §1.4-1.7, pp. 3-6
  2. Python documentation — An Informal Introduction to Python
  3. Python documentation — Built-in Types

Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108