Almost every program you will ever write starts the same way: you take a value, give it a name, and use that name later. That name is a variable. This page walks through what really happens when Python runs x = 5, why the = sign doesn't mean what it meant in maths class, and the one surprise that catches nearly every beginner.

A name that points at a value

Run this line in Python:

age = 30

Python does two things, in this order. First it creates the value 30 somewhere in the computer's memory. Then it attaches the name age to it. From now on, whenever you write age, Python looks up the name, follows it to the value, and uses 30.

You may have heard variables described as boxes that hold a value. That picture works for some languages, but in Python a better picture is a name tag on a string: the value lives on its own, and the name is a label tied to it. You can move the label to another value, and two labels can be tied to the same value. Keep that picture in mind; it explains everything below.

Step through this little program and watch the names (left) and the values in memory (right).

Step through it · program 1

names
values in memory

The = sign means "make this name point here"

In maths, age = age + 1 is nonsense: no number equals itself plus one. In Python the = is not a statement of fact, it's an instruction, and it's called assignment. Python always handles it in two steps:

The old 30 isn't changed; it just has no name pointing at it any more, so your program can't reach it and Python is free to clean it up. That's why in the stepper above the old value fades out instead of turning into 31. Numbers and strings in Python can never be edited in place. You can only make a name point at a new one.

When you want to compare two things, use a double equals: age == 31 asks "does age point to something equal to 31?" and gives back True or False. Mixing up = and == is one of the most common beginner typos, in every language.

Because the right side is worked out first, the order of lines matters. A name has to exist before you use it. Try to read a name you haven't assigned yet and Python stops with an error:

print(score)
NameError: name 'score' is not defined

You'll see this message a lot, usually because of a typo (scroe instead of score) or because the line that creates the variable comes after the line that uses it. Recent versions of Python even guess what you meant: Did you mean: 'score'?

Two names, one value

Here is the surprise. When you write b = a, Python does not make a copy. It ties a second label to the same value. With numbers and text you never notice, because those can't be changed, only replaced. But some values can be changed in place. A list is one of them: append adds an item to the existing list rather than building a new one.

Pick a version and step through it. Watch the arrows.

Step through it · program 2

names
values in memory

In the first version, a and b are two labels on one list, so a change made "through" b shows up when you look through a. If you want an independent list, ask for one explicitly with a.copy() (or list(a), or a[:]). In the numbers version, x = x + 1 moves the label x to a new value and leaves y where it was.

You don't need to worry about this all the time. The rule to remember is short: assignment never copies. It only points a name at a value.

A name can point at any kind of value

Python never asks you to say in advance what kind of value a variable will hold. The value itself knows its type, and you can ask with type():

price = 4.99          # a float (a number with a decimal point)
count = 3             # an int (a whole number)
title = "Coffee"      # a str (text, in quotes)
in_stock = True       # a bool (True or False)

print(type(price))   # <class 'float'>

Because the type belongs to the value and not to the name, a name can be moved to a value of a different type later: count = "three" is allowed. Allowed isn't the same as wise, though. If count is a number on one line and text on another, the next person to read your code (often you, a week later) will be confused. Languages like Java or C take the other approach and fix a variable's type when you declare it; Python's flexible style is called dynamic typing.

Types matter the moment you combine values. count + 1 gives 4, but title + 1 fails with a TypeError, because Python won't guess whether you wanted maths or text. Convert explicitly: title + str(1) gives "Coffee1".

What you're allowed to call a variable

Python has a few hard rules for names, and a few conventions that every Python programmer follows. The rules:

The conventions: use lowercase words joined with underscores (total_price, called snake_case), write constants in capitals (MAX_PLAYERS), and pick names that say what the value means. seconds_left beats s and x2. Type any name below to check it.

Name checker

One trap the checker flags in orange: names like list, str, print or input are allowed, because they're not keywords. They're names Python already uses for built-in tools. Write list = [1, 2] and you've moved the label list away from Python's list tool, so a later list("abc") fails with a confusing error. Pick another word.

Check yourself

Predict what each snippet prints, then pick an answer.

x = 10
y = x
x = 20
print(y)

y = x ties y to the value 10. Then x = 20 moves only the x label. y still points to 10.

colors = ["red"]
paint = colors
paint.append("blue")
print(colors)

paint and colors are two labels on one list. append changes that list in place, so both names see it.

n = 5
n = n * 2 + 1
print(n)

Right side first: 5 * 2 + 1 is 11. Then n is pointed at 11. Using a name on both sides is completely normal.

my-score = 0

Python reads the hyphen as a minus sign, so this looks like my - score = 0, which isn't something you can assign to. Use my_score.

The short version

Next time you read total = total + price in someone's code, you'll see it the way Python does: work out a new number, move the label.