Chapter 1
Values and Types
Every Python program is built out of values: the actual pieces of data a
script works with. A price is a value. A name is a value. This chapter is
about the handful of value types you'll use constantly, and about print(),
the tool you'll use to look at them.
Python as a calculator
Open a terminal and type python with nothing after it. You'll land in the
REPL, a prompt that reads one line, runs it, and shows you the result
right away:
$ python
>>> 4.50 + 12.00
16.5
>>> exit()Type exit() (or press Ctrl-D on macOS/Linux, Ctrl-Z then Enter on Windows)
to leave. The REPL is a scratchpad: perfect for trying one thing, not for
saving work. From here on this book shows code as a script instead, exactly
as you'd save and run it, and every one of those scripts is run for real
while the book is built.
4.50 + 12.00
Notice that printed nothing. In the REPL, typing an expression on its own
shows you its result automatically. In a script, it doesn't: nothing happens
to a value unless you do something with it, usually print().
print(4.50 + 12.00)
16.5+ here is an operator: a symbol that combines values into a new one.
4.50 + 12.00 is itself an expression, a piece of code that produces a
value, and print() is what shows you that value.
Numbers: int and float
Python has two everyday number types. A whole number, with no decimal point,
is an int:
print(3)
print(type(3))
3
<class 'int'>type() is a function that tells you a value's type, what kind of thing
it is. A number with a decimal point is a float:
print(4.50)
print(type(4.50))
4.5
<class 'float'>Notice 4.50 printed as 4.5. Python doesn't remember a trailing zero you
typed; a float is just its numeric value, not the exact digits you wrote.
The usual arithmetic operators all work the way you'd expect, with two worth slowing down on:
print(7 / 2)
print(7 // 2)
print(7 % 2)
3.5
3
1/ is true division and always gives you a float, even when it divides
evenly. // is floor division: divide, then drop anything after the
decimal point, keeping an int if both sides were int. % is the
remainder, what's left over after dividing as many whole times as
possible. 7 // 2 is 3 with 1 left over, which is exactly what 7 % 2 gives
you.
print(2 ** 10)
1024** is exponentiation: 2 to the 10th power.
Try it
In your own script, print the result of 10 % 3 before you run it, guess
the answer, then check.
A float surprise worth knowing about now
print(0.1 + 0.2)
0.30000000000000004That's not a bug in this book's example, and it's not a bug in Python. A
float stores a number in binary, and most decimal fractions, including
0.1, don't have an exact binary equivalent, the same way 1/3 has no
exact ending in decimal. The stored value is a tiny bit off, and usually
that's invisible, until you add two of them and the tiny errors don't quite
cancel out. Two things follow from this: never compare two floats with ==
expecting them to match exactly if either came from arithmetic, and when you
need money to look right, round it for display (you'll use f"{x:.2f}" for
exactly that, starting in Chapter 2), and keep the underlying calculation
running on the un-rounded number for as long as possible.
Strings
Text in Python is a str, written in either single or double quotes; they
mean the same thing, so pick one and be consistent:
item = "coffee"
print(item)
print(type(item))
coffee
<class 'str'>+ on strings concatenates them, joins them end to end. It does not add
a space for you:
print("flat" + "white")
print("flat" + " " + "white")
flatwhite
flat whitelen() counts characters, including spaces:
print(len("coffee"))
print(len("flat white"))
6
10You can't concatenate a string and a number directly:
print("Total: " + 4.50)
That raises TypeError: can only concatenate str (not "float") to str.
Python won't silently guess whether you meant "4.50" the text or 4.50 the
number, because they're genuinely different things. You'll fix this properly
with f-strings in Chapter 2; for now, str() converts a value to text
explicitly:
print("Total: " + str(4.50))
Total: 4.5A few string methods you'll use constantly
A str comes with methods, functions attached to the value itself,
called with a dot. You've already used one, len() isn't a method (it's a
plain function), but the ones below are, and you'll reach for them often
enough to learn them now rather than as you stumble into each one later.
item = " Flat White "
print(item.strip())
print(item.strip().lower())
print(item.strip().upper())
Flat White
flat white
FLAT WHITE.strip() removes whitespace from both ends, useful for text that came from
somewhere messy, like a line read from a file. .lower() and .upper()
return a new string in that case; they don't change the original.
item = "flat white"
print(item.replace("flat", "iced"))
print(item)
iced white
flat white.replace() also returns a new string rather than changing item in
place. This is true of every string method: a str can't be changed after
it's created, only used to build a new one. That's worth remembering
alongside Chapter 5's point about lists being the opposite, changeable in
place.
item = "flat white"
print(item.startswith("flat"))
print(item.endswith("latte"))
print("white" in item)
True
False
True.startswith() and .endswith() check the ends of a string. Plain in
checks whether one string appears anywhere inside another, not just lists,
which you'll meet properly in Chapter 5.
.split() breaks a string into a list of pieces, and .join() does the
reverse, gluing a list of strings back together with a separator in
between:
categories = "coffee,transit,groceries"
as_list = categories.split(",")
print(as_list)
back_together = " and ".join(as_list)
print(back_together)
['coffee', 'transit', 'groceries']
coffee and transit and groceriesYou'll use .split() for real starting in Chapter 9, to pull apart a line
read from a file.
print() with more than one thing
print() takes as many arguments as you like, separated by commas, and joins
them with a space by default:
item = "coffee"
price = 4.50
print(item, price)
coffee 4.5Change the separator with sep=:
print(item, price, sep=" costs $")
coffee costs $4.5sep= is a keyword argument: you're telling print() which setting
you're changing by name, rather than by position. Chapter 7 covers this
properly when you write your own functions that accept them.
Practice
Try each of these before you read the solution under it.
- Print the result of dividing 100 by 7 with
/, then with//, then the remainder with%, one per line. - Given
first = "flat"andsecond = "white", print them joined with a single space between them, without changing either variable. print()a coffee's name and its price on one line, separated by the text" -> ", usingsep=.- Given
raw_note = " Flat White, extra hot ", clean it up to"flat white, extra hot": strip the whitespace, lowercase it, and print the result.
Solutions
1. Three separate print() calls, one per operator.
print(100 / 7)
print(100 // 7)
print(100 % 7)
14.285714285714286
14
22. + needs the space added by hand; it never adds one for you.
first = "flat"
second = "white"
print(first + " " + second)
flat white3. sep= changes what goes between the arguments, not what comes before
or after all of them.
name = "cappuccino"
price = 4.20
print(name, price, sep=" -> ")
cappuccino -> 4.24. Chain the methods: .strip() first, then .lower() on what it
returns.
raw_note = " Flat White, extra hot "
print(raw_note.strip().lower())
flat white, extra hotWhere this leaves you
You can tell Python's core value types apart, do arithmetic including the two
kinds of division, work with strings and know why you can't glue one to a
number without converting it first, and use print() with more than one
value. Chapter 2 gives values names that stick around, variables, and takes
input from whoever is running your script.