Chapter 2 · Getting Started

Numbers, Text & Lists

Use Python as a calculator, slice strings like a pro, meet the list, and write your first loop. Along the way, find out why 0.1 + 0.2 is not 0.3.

You will learn

  • Integer and float arithmetic, including /, //, % and **.
  • Why floating-point numbers are slightly inexact, and what to do about it.
  • Strings: quotes, escapes, raw strings, indexing, slicing and immutability.
  • Lists: indexing, slicing, changing items, and the "two names, one list" trap.
  • Multiple assignment, while loops, and print() options.

Numbers

The REPL works like a calculator. Type an expression and it shows the value. + - * / work as you expect, and parentheses group.

Python has two main number types:

Four kinds of division-ish operators

OperatorNameExampleResult
/true division (always a float)17 / 35.666666666666667
//floor division (rounds down)17 // 35
%remainder (modulo)17 % 32
**power2 ** 7128

☕ Java / 🟨 JS: in Java, 17 / 3 is 5 (integer division). In Python it is 5.666…. Use // when you want Java's behaviour. There is no ++ or -- in Python: write x += 1. Unlike JS, int and float are different types.

⚠️ Pitfall: negatives round toward minus infinity. // rounds down, not toward zero. The sign of % follows the divisor. Java and JS do it the other way.

Precedence: ** binds tighter than unary minus

Variables and mixed types

= gives a value a name. Using a name that was never assigned is an error. Mixing int and float gives a float.

Handy built-ins: abs(-3) is 3, round(3.7) is 4, int(3.9) is 3 (it truncates toward zero), float("2.5") is 2.5. Python also has complex numbers (3+5j), and Decimal and Fraction types (Chapter 14).

Floating point: why 0.1 + 0.2 ≠ 0.3

Computers store floats in binary (base 2). Many decimal fractions, like 0.1, cannot be written exactly in binary. It is the same as 1/3 in decimal: 0.3333… never ends. So Python stores the closest binary number it can.

Analogy: you measure a table with a ruler marked only in 1/8 inches. Most lengths come out a tiny bit off. The errors are small, but they can add up.

❌ Never compare floats with ==

✅ Compare with a tolerance

💡 Tip: for money, store whole cents as int (1999 instead of 19.99), or use decimal.Decimal (Chapter 14). This is the same advice as Java's BigDecimal, and it is not a Python bug. Every language that uses IEEE-754 floats behaves this way, JS and Java included.

Text (strings)

A string (str) is a sequence of characters. Use single quotes '…' or double quotes "…"; they mean the same thing. Pick whichever lets you avoid escaping.

The REPL shows a string's representation (with quotes). print() shows the text itself.

There is no separate char type: one character is just a string of length 1.

Raw strings and triple quotes

In a raw string (r"..."), backslashes are not special. That is useful for Windows paths and regular expressions (Chapter 13). Triple quotes ("""…""") let a string span several lines.

⚠️ Pitfall: an unknown escape like "\d" still works today, but Python prints SyntaxWarning: "\d" is an invalid escape sequence. A future version will make it an error. Use raw strings for regex patterns and Windows paths.

Joining and repeating

Joining adjacent literals is handy for breaking a long string across lines inside parentheses.

Indexing and slicing

Each character has an index (position) starting at 0. Negative indexes count from the end: -1 is the last character.

Think of the indexes as pointing between characters. The slice word[i:j] is everything between edge i and edge j. The start is included and the end is excluded.

An index that is too big is an error. A slice that is too big is quietly trimmed:

Strings are immutable

Immutable means "cannot be changed after it is created". You build a new string instead.

❌ Wrong

✅ Right

Everyday string methods

A method is a function attached to an object, called with a dot: text.upper(). Methods never change the original string; they return a new one.

☕ Java / 🟨 JS: str.join is "backwards" compared with JS: you call it on the separator, as in ", ".join(items), while JS writes items.join(", "). Compare strings with ==; there is no .equals().

Lists

A list holds an ordered sequence of items in square brackets. It is like a Java ArrayList or a JS array. Items can be of any type, though usually they are all the same type.

Unlike strings, lists are mutable: you can change them in place.

Lists can contain other lists (nesting):

Two names, one list (aliasing)

Assignment never copies. b = a makes b a second name for the same list. It is like two labels on one box. A slice, on the other hand, creates a new (shallow) copy.

☕ Java: this is exactly how object references behave in Java and JS. Python simply has no primitive types: every value, even 3, is an object, and every variable is a reference. Appendix A goes deeper.

First steps towards programming

Here is the classic Fibonacci series, where each number is the sum of the two before it. Read the comments line by line.

print() takes extra keyword arguments. end replaces the newline at the end, and sep replaces the space between items.

More examples

1. Splitting a bill

2. Cleaning up a messy expense note

3. File extension and name

4. Running totals in a list

5. Is it a palindrome?

Recap

  • / always gives a float. // floors, % follows the divisor's sign, and ** is power (it binds tighter than unary minus).
  • Floats are binary approximations: compare with math.isclose, and use integer cents or Decimal for money.
  • Strings are immutable sequences: index from 0 or from the end with negatives; slices include the start and exclude the end.
  • Lists are mutable. Assignment shares the list; lst[:] copies it.
  • a, b = b, a + b evaluates the right side first. while loops on a condition. print(..., sep=, end=) controls output.

Exercises

Exercise 1 🟢 easy predict the output

Predict each result: 7 / 2, 7 // 2, 7 % 2, 2 ** 4.

Show solution

3.5, 3, 1, 16. Plain / always gives a float, even when the division is exact (8 / 4 is 2.0).

Exercise 2 🟢 easy predict the output

With s = "expense", what are s[0], s[-1], s[2:5], s[:3] and s[::2]?

Show solution

The slice [2:5] takes indexes 2, 3 and 4. The step 2 takes every other character, starting at index 0: e, p, n, e.

Exercise 3 🟢 easy fix the bug

The goal is to capitalise the first letter. Fix the code.

Show solution

Strings are immutable, so you build a new string and rebind the name to it.

Exercise 4 🟢 easy predict the output

What does this print?

Show solution

[1, 2, 3, 4] 4. b = a does not copy the list; both names point to the same list object.

Exercise 5 🟡 medium predict the output

Predict: -7 // 2, -7 % 2, -2 ** 2, int(-3.7).

Show solution

-4, 1, -4, -3. // rounds toward minus infinity, so % takes the divisor's sign. ** runs before unary minus. int() truncates toward zero, which is different from //.

Exercise 6 🟡 medium explain why

This loop adds 0.1 ten times. Why does it print False? How should you check it instead?

Show solution

0.1 has no exact binary form, and the tiny error in each addition adds up. Compare floats with a tolerance. The built-in sum() uses a more careful algorithm, so it hides the error in this case, but it can't help with == on floats in general.

Exercise 7 🟡 medium build it · playground

Create playground/initials.py that turns full_name = "ada lovelace byron" into A.L.B., using split, indexing and upper.

Show solution

parts[i][0] indexes twice: first the list, then the string. Chapter 3's for loop will make this shorter.

Exercise 8 🟡 medium refactor it

Rewrite this swap without the temporary variable.

Show solution

The right-hand side is evaluated completely before any name is reassigned.

Exercise 9 🔴 hard predict the output

What is the final value of letters?

Show solution

['_', 'a', 'X', 'd', 'e', 'Y', 'Z']. Assigning to a slice can change the list's length. The first step replaces two items with one. The second replaces the last item with two. [:0] is an empty slice at the start, so assigning to it inserts.

Exercise 10 🔴 hard mini-project · playground

Create playground/receipt.py. Given prices = [499, 1250, 99, 2000] (in cents), print each price as euros on its own line with print(..., sep=""), like €4.99. Then print the total and the average (in euros, rounded to 2 decimals). Use a while loop, // and %, and no floats until the average.

Show solution

Output: €4.99, €12.50, €0.99, €20.00, Total: €38.48, Average: €9.62. Whole cents keep every sum exact. The cents formatting is clumsy here; Chapter 9's f-strings shrink it to f"{p / 100:.2f}".

Official docs