input() always hands you a string#
A first program that asks a question and does arithmetic with the answer. It looks finished:
age = input("How old are you? ")
print("Next year you will be", age + 1)
What happens when you type 30? Decide before you scroll.
Traceback (most recent call last):
File "age.py", line 2, in <module>
print("Next year you will be", age + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to str
Read the last line literally, because it is telling you exactly what it thinks you asked for: it believes
age is a str, and you asked it to join a string to the number 1. It is right.
input() always returns a string — every time, no matter what the person types.
Typing digits does not make it a number, and there is nothing about the prompt text that changes this.
Convert it, on the way in:
age = int(input("How old are you? "))
print("Next year you will be", age + 1)
How old are you? 30
Next year you will be 31
And int() is strict about what it will accept:
print(int("3.7"))
ValueError: invalid literal for int() with base 10: '3.7'
int() converts a string that spells a whole number. "3.7" does not, so it
refuses rather than guessing whether you wanted 3 or 4. If the person might type a decimal, use
float(input(...)); if you need a whole number from a decimal string, convert twice
— int(float("3.7")), which gives 3.
Convert at the moment of input, not later. If you write age = input(...) and convert somewhere further down, then every line in between is working with a string, and each one fails differently: age + 1 raises TypeError, age * 2 silently gives you the digits twice, and age > 18 raises TypeError as well. One conversion on the input line removes all three.
The types you actually meet#
A first Python course uses four types constantly, and type() will tell you which one you are
holding whenever you are unsure:
| Type | What it holds | Literal | type() says |
|---|---|---|---|
int | whole numbers, no size limit | 42 | <class 'int'> |
float | numbers with a decimal point | 3.14 | <class 'float'> |
str | text, in quotes | "hello" | <class 'str'> |
bool | only True or False | True | <class 'bool'> |
Two things about that table get examined. First, 42 and "42" are different values of
different types that print identically — which is why a program can look right on screen and still be wrong.
Second, bool is quietly a kind of int:
print(True + True)
print(isinstance(True, int))
2
True
True counts as 1 and False as 0. That is not a curiosity — it is why
sum(results) over a list of booleans counts how many are true, and it is a favourite exam question.
Three kinds of division#
Python has more division than most languages, and the exam knows it:
print(7 / 2)
print(7 // 2)
print(7 % 2)
print(-7 // 2)
print(2 ** 10)
3.5
3
1
-4
1024
| Operator | Name | Gives |
|---|---|---|
/ | true division | always a float, even 4 / 2 is 2.0 |
// | floor division | a whole number, rounded down |
% | modulo | the remainder — the tool for "is it even", "last digit", "wrap around" |
** | exponent | power. 2 ** 10, not 2 ^ 10 |
Look again at -7 // 2 giving −4. Floor division rounds toward negative
infinity, not toward zero — it does not chop the decimal off, it goes down. Positive numbers hide
this, because rounding down and chopping agree there. Negative numbers do not.
7 / 2 in those languages is 3, because two whole numbers give whole-number division. In Python 3 it is 3.5. The habit transfers badly in both directions, and it is a common source of an answer that is off by exactly the fractional part.
Decimals are not exact#
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
0.30000000000000004
False
Not a bug. A float stores numbers in binary, and one tenth has no exact binary form, exactly as
one third has no exact decimal form. The sum lands a hair above 0.3, and == compares honestly and
says no.
So never compare floats with ==. Either round for display —
round(0.1 + 0.2, 2) gives 0.3 — or test that the difference is small enough:
abs(a - b) < 1e-9. For money, work in whole cents as int.
A variable is a name, not a box#
Most explanations say a variable is a box you put a value in. That picture is fine until the day it costs you marks. Python's actual model is simpler: a variable is a name attached to a value. Assignment moves the name; it does not fill a container.
count = 5
count = count + 1
print(count)
6
Read the middle line right to left, which is the order Python does it in: work out count + 1
— that is 6 — then attach the name count to it. It is not an equation claiming that
count equals count plus one, which would be false. = is an instruction, not
a claim. count += 1 is shorthand for exactly the same thing.
Once a value is a list rather than a number, two names can be attached to the same list, and changing it through one name changes what you see through the other. That surprise is the single highest-yield question in a first Python course, and it makes sense immediately if you already think of names pointing at values. It has its own guide: why changing one list changed the other.
Naming rules Python enforces, and the ones it does not#
Two of these are errors and one is silent, which is the dangerous one:
2nd = 5
SyntaxError: invalid decimal literal
A name cannot start with a digit. The message talks about a number because Python started reading
2 as one and then found a letter glued to it.
class = 5
SyntaxError: invalid syntax
class is a keyword. So are if, for, while,
def, return, in, not, and, or,
None, True and False. You do not need to memorise the list — a
decent editor colours them, and the error arrives instantly.
Score = 1
score = 2
print(Score, score)
1 2
This is the silent one. Python is case sensitive, so Score and
score are two unrelated variables. No error, no warning — just a program that updates one name
and reads the other. The convention that prevents it is snake_case: lowercase words joined by
underscores, final_score, every time.
Printing things next to each other#
Two ways to put a label in front of a number, and they are not the same:
n = 5
print("n =", n)
print("n = " + str(n))
n = 5
n = 5
Identical output, different mechanisms. The comma passes two separate arguments to
print, which converts each one and joins them with a space for you — it never raises a
TypeError, whatever the types. The + is string concatenation, which demands that both sides already
be strings, which is why str(n) is there and why dropping it produces the same TypeError
this guide opened with.
Two options change the joining:
print("a", "b", sep="-")
print("x", end="")
print("y")
a-b
xy
sep replaces the space between arguments; end replaces the newline
print normally adds at the end, which is how you build one line of output from several
print calls inside a loop.
Where these go wrong#
- Doing arithmetic on
input()without converting. The single most common first-course bug.int(input(...))orfloat(input(...)), on the input line. - Using
/where a count is wanted.len(xs) / 2is a float, so it cannot index a list.len(xs) // 2can. - Comparing floats with
==. It compiles, it runs, and it saysFalsefor values that print identically. - Comparing numbers that are still strings.
"10" < "9"isTrue— that is alphabetical order, not numeric.10 < 9isFalse. No error either way. - A capitalisation typo in a variable name. Silent, and it looks like the assignment did not
happen.
snake_caseeverywhere makes it rare. - Expecting
-7 // 2to be −3. Floor division rounds down, not toward zero. - Assuming
4 / 2is anint. It is2.0. Anything printed from it carries the.0.
Test yourself in the free Kestrel Exams app
Topic-selectable practice — offline, no ads, no account.
Practice this topic →Frequently asked questions#
Why does input() + 1 give a TypeError?
Because input() always returns a string, even when the person types digits. "30" + 1 asks Python to join text to a number, which it refuses to guess at. Convert on the input line: age = int(input("How old are you? ")). Use float() instead if a decimal is possible.
What is the difference between / and // in Python?
/ is true division and always produces a float, so 7 / 2 is 3.5 and even 4 / 2 is 2.0. // is floor division and produces a whole number rounded down, so 7 // 2 is 3. Rounding down is not the same as chopping the decimal off: -7 // 2 is −4, not −3.
Why does int("3.7") fail?
int() converts a string that spells a whole number, and "3.7" does not, so it raises ValueError rather than guessing between 3 and 4. Use float("3.7") to get 3.7, or int(float("3.7")) to get 3.
Is Python case sensitive for variable names?
Yes. Score and score are two completely separate variables, and using the wrong one produces no error at all — just a program that stores a value under one name and reads another. The snake_case convention makes this mistake rare.
Why is 0.1 + 0.2 not equal to 0.3 in Python?
Floats are stored in binary, and one tenth has no exact binary representation, just as one third has no exact decimal one. The sum comes out as 0.30000000000000004. Never compare floats with ==; round for display, or test that abs(a - b) is smaller than a small tolerance.
Is True really a number in Python?
Yes. bool is a subclass of int, with True worth 1 and False worth 0. True + True is 2. This is why sum() over a list of booleans counts how many are true.
Something here not clear? A topic you wish we covered? Tell us. We read every message, and a request is the fastest way to get a guide written — several of these exist because somebody asked.
