Variables: Naming Things 📦
A program that cannot remember anything can only do one thing. Variables are how a program remembers, and naming them well is a genuine craft.
A label stuck on a value
name = "Guybrush"
grog = 7
print(name)
print(grog)
Guybrush
7
The = is not the equals of mathematics. Read it as "gets" or "is now":
name gets "Guybrush". It is an instruction, and it always runs right to left:
work out the value on the right, then attach the label on the left.
This is why x = x + 1 is not the nonsense it looks like. The right side is computed first using the old value, and only then is the label moved to the answer. In maths that line has no solutions. In programming it means 'add one'.
Changing your mind
score = 0
print("Start:", score)
score = 10
print("After one insult:", score)
score = score + 5
print("After the follow-up:", score)
score += 5 # the same thing, written the way everyone writes it
print("Final:", score)
Start: 0
After one insult: 10
After the follow-up: 15
Final: 20
A variable is a label, and labels can move. Nothing is carved in stone.
+= is shorthand, and its family is worth memorising now:
| Shorthand | Means | Example |
|---|---|---|
x += 3 | x = x + 3 | add |
x -= 3 | x = x - 3 | subtract |
x *= 2 | x = x * 2 | double |
x /= 2 | x = x / 2 | halve |
In Rust, variables are locked by default and you must ask for permission to change one. Python is the opposite: everything is changeable, always, and it trusts you completely. That trust is why Python is fast to write and why big Python programs need discipline that the compiler will not enforce for you.
Python never asks you for a type
thing = 42
print(thing, type(thing))
thing = "now I am text"
print(thing, type(thing))
thing = 3.5
print(thing, type(thing))
42 <class 'int'>
now I am text <class 'str'>
3.5 <class 'float'>
The value has a type; the label does not. This is called dynamic typing, and it is a huge part of why Python feels light. It is also how you get a program that runs fine for a month and then explodes because a variable you assumed was a number turned out to be text. Level 4 shows you type hints, which let you write down your assumptions so tools can check them.
The rules for names
| Rule | Good | Bad |
|---|---|---|
| Letters, digits and underscores only | player_2 | player-2 (that is a minus sign) |
| Cannot start with a digit | score_1 | 1st_score |
| Case matters | name and Name are different | assuming they are the same |
| No spaces | total_gold | total gold |
| Not a Python keyword | class_name | class, for, if |
And the conventions, which are not rules but might as well be:
- lower_case_with_underscores for variables and functions. This is called snake_case and, yes, that is a happy coincidence.
- ALL_CAPS for things that should never change:
MAX_PLAYERS = 8. - CapWords for classes, which you meet in Lesson 31.
These come from PEP 8, Python's official style guide. Following it means any Python programmer on earth can read your code without friction. It is worth the ten seconds.
Naming is the actual skill
# Technically fine. Humanly useless.
a = 5
b = 3
c = a * b
# What the same code should look like
rows = 5
seats_per_row = 3
total_seats = rows * seats_per_row
print(f"The theatre holds {total_seats} people.")
The theatre holds 15 people.
Both versions run identically. Only one of them can be understood at 2am during an outage. There is an old joke that the two hard problems in computer science are cache invalidation, naming things, and off-by-one errors. The joke is only funny because the middle one is true.
A name is an argument you are making about what something is. 'data' claims nothing. 'unpaid_invoices' claims a great deal, and if the variable ever holds a paid invoice, the name itself becomes the bug report.
Several at once
x, y = 10, 20
print(x, y)
x, y = y, x # swap, with no temporary variable
print(x, y)
a = b = c = 0 # all three point at the same 0
print(a, b, c)
10 20
20 10
0 0 0
That swap line is a small piece of Python showing off. In most languages it takes three lines and a temporary variable. You will use it more than you expect.
Python reads top to bottom. Using a variable before you have assigned it gives you NameError: name 'total' is not defined. Ninety percent of the time that means a typo: totl in one place and total in another. Python will not guess what you meant, and that is a kindness.
Ship's manifest
Create variables for a ship's name, its crew size and its top speed in knots. Print a sentence using all three. Then the crew grows by 4: update the variable and print the sentence again.
Reveal solution
ship_name = "Sea Monkey"
crew_size = 12
top_speed = 9.5
print(f"The {ship_name} sails with {crew_size} crew at {top_speed} knots.")
crew_size += 4
print(f"After recruitment: {crew_size} crew.")
The Sea Monkey sails with 12 crew at 9.5 knots.
After recruitment: 16 crew.Predict the output
Do not run it. What does this print, and why?
a = 5
b = a
a = 100
print(a, b)Reveal solution
100 5.
b = a copied the value that a was pointing at, at that moment. It did not tie the two labels together. Changing a afterwards has no effect on b.
Keep this picture. In Lesson 11 you will meet lists, where the same line behaves quite differently, and this is the memory that will save you.
Rename for clarity
Rewrite this so a stranger could understand it in one read.
p = 24.99
q = 3
r = p * q
s = r * 0.2
t = r + s
print(t)Reveal solution
price_each = 24.99
quantity = 3
subtotal = price_each * quantity
vat = subtotal * 0.2
total = subtotal + vat
print(f"Total including VAT: {total:.2f}")
Total including VAT: 89.96The :.2f means 'show this number with two decimal places', which you will meet properly in Lesson 4. Without it you would get 89.964, and money with three decimal places makes accountants reach for their pens.