Variables and assignment
Explain names, binding and mutation, and trace how a program's variables change as it runs.
What you will learn
- Explain a variable as a name bound to a value
- Trace assignments and reassignments in a variable table
- Distinguish rebinding a name from mutating a value
- Choose clear names and use constants for fixed values
On this page
A program that could only handle values written directly into its code would be a calculator with a fixed answer. Variables let a program hold on to results, give them meaningful names, and use them later.
Names and values
A variable is a name that refers to a value. Assignment is the act of attaching a name to a value, and the symbol for it is usually =.
Python
score = 10JavaScript
let score = 10;Java
int score = 10;C
int score = 10;Despite the symbol, = does not mean “equals” as in mathematics. It means “evaluate the right side, then store the result under the name on the left”. That is why this is legal and meaningful:
score = score + 1Read it as: take the current value of score, add one, store the answer back in score. As algebra it would be nonsense; as an instruction it is one of the most common lines in programming.
Two parts of the picture to keep apart:
- The name (
score) is a label. - The value (
10) is the data, with a type.
In statically typed languages such as Java and C, the name also carries a declared type (int). In Python and JavaScript, only the value has a type, and the name can later point at a different kind of value.
Reassignment and tracing
Assigning to a name that already exists rebinds it. The old value is forgotten (if nothing else refers to it). A variable table records this:
price = 20quantity = 3total = price * quantityquantity = quantity + 1| After line | price |
quantity |
total |
|---|---|---|---|
| 1 | 20 | - | - |
| 2 | 20 | 3 | - |
| 3 | 20 | 3 | 60 |
| 4 | 20 | 4 | 60 |
Note that total stays 60 on line 4. It was computed once, from the values at that moment. It does not track quantity. Beginners often expect a variable to behave like a spreadsheet formula; it does not.
The same four lines as a program, which prints the variables after the last line:
Python
price = 20quantity = 3total = price * quantityquantity = quantity + 1print(price, quantity, total)JavaScript
let price = 20;let quantity = 3;let total = price * quantity;quantity = quantity + 1;console.log(price, quantity, total);Java
public class TraceVars { public static void main(String[] args) { int price = 20; int quantity = 3; int total = price * quantity; quantity = quantity + 1; System.out.println(price + " " + quantity + " " + total); }}C
#include <stdio.h>
int main(void) { int price = 20; int quantity = 3; int total = price * quantity; quantity = quantity + 1; printf("%d %d %d\n", price, quantity, total); return 0;}All four print the last row of the table:
20 4 60Swapping two variables
The classic puzzle: exchange the values of a and b. You cannot just write a = b then b = a, because the first line destroys the original a. The method that works in every language is a temporary variable: park one value, overwrite, then restore.
a b temp1 2 - start1 2 1 temp = a2 2 1 a = b2 1 1 b = tempPython
a = 1b = 2temp = aa = bb = tempprint(a, b)JavaScript
let a = 1;let b = 2;const temp = a;a = b;b = temp;console.log(a, b);Java
public class SwapTemp { public static void main(String[] args) { int a = 1; int b = 2; int temp = a; a = b; b = temp; System.out.println(a + " " + b); }}C
#include <stdio.h>
int main(void) { int a = 1; int b = 2; int temp = a; a = b; b = temp; printf("%d %d\n", a, b); return 0;}All four print:
2 1Some languages can skip the temporary with simultaneous assignment, which evaluates the whole right side before storing anything. Java and C have no such syntax, so they always use the temporary.
Python
a, b = 1, 2a, b = b, aprint(a, b)JavaScript
let a = 1;let b = 2;[a, b] = [b, a];console.log(a, b);Java
Java has no simultaneous assignment. Use the temporary variable shown above.
C
C has no simultaneous assignment. Use the temporary variable shown above.
Both programs print 2 1.
A third trick swaps numbers with arithmetic and no spare variable: a = a + b, then b = a - b, then a = a - b. It only works for numbers, and it can overflow in languages with fixed-size integers. Treat it as a curiosity.
Rebinding versus mutating
After one variable is assigned to another, something surprising can happen. Take a list, give it a second name, and change the list through the second name:
x -----> [1, 2]y = x (now both names point at the same list)
x ---+ +--> [1, 2, 3] after adding 3 through yy ---+Python
x = [1, 2]y = xy.append(3)print(x, y, x is y)JavaScript
const x = [1, 2];const y = x;y.push(3);console.log(x, y, x === y);Java
import java.util.ArrayList;import java.util.List;
public class AliasList { public static void main(String[] args) { List<Integer> x = new ArrayList<>(List.of(1, 2)); List<Integer> y = x; y.add(3); System.out.println(x + " " + y + " " + (x == y)); }}C
C arrays cannot grow, so this version changes an existing slot instead of appending. The pointer y holds the address of x’s first element.
#include <stdio.h>
int main(void) { int x[3] = {1, 2, 0}; int *y = x; y[2] = 3; printf("%d %d %d, same place: %d\n", x[0], x[1], x[2], x == y); return 0;}Python prints [1, 2, 3] [1, 2, 3] True, JavaScript prints [ 1, 2, 3 ] [ 1, 2, 3 ] true, Java prints [1, 2, 3] [1, 2, 3] true, and C prints 1 2 3, same place: 1. In every language the change made through y shows up in x, because there is only one list and two names for it. The identity check at the end confirms it.
- Rebinding:
y = something_elsepoints the nameyat a different value. Other names are unaffected. - Mutation: changing the contents of the value itself. Every name pointing at it sees the change.
Simple values like numbers and strings are typically immutable (they cannot be changed in place), so the issue arises with collections and objects. The lesson on memory and references covers this properly; for now, remember that = between variables does not always copy.
Constants and naming
A constant is a name that should not change after it is set.
Python
MAX_ATTEMPTS = 3 # capital letters by convention; Python will not stop you reassigningJavaScript
const MAX_ATTEMPTS = 3; // reassigning is an errorJava
final int MAX_ATTEMPTS = 3; // reassigning is a compile errorC
const int MAX_ATTEMPTS = 3; /* reassigning is a compile error */Some languages enforce this and some rely on convention. Either way, giving a fixed number a name such as MAX_ATTEMPTS beats scattering a bare 3 through your code: the name says what it means, and you change it in one place.
For naming in general:
- Pick names that say what the value is:
elapsed_secondsrather thanxordata2. - Follow your language’s convention. Python and C favour
snake_case; JavaScript and Java favourcamelCase. Constants are usuallyUPPER_SNAKE_CASE. - Names are case-sensitive in nearly every language:
totalandTotalare different. - Names usually cannot start with a digit or contain spaces, and cannot reuse reserved words such as
iforwhile.
Common pitfalls
- Using a variable before it has a value. Most languages report this as an error; C may silently give you garbage.
- Expecting
=to link values. Changingquantitydoes not update an earliertotal. - Typos in names. In a dynamic language, misspelling a name on assignment can silently create a new variable instead of updating the old one.
- Reusing one name for unrelated purposes. A variable that is a count on line 5 and a filename on line 20 invites bugs.
- Assuming assignment copies. For collections it often shares.
Trace this program and give the final values of a, b and c. There is no input.
a = 5b = a * 2a = a + bc = a - bb = cExpected: three whole numbers, one for each variable.
Show solution
| After line | a |
b |
c |
|---|---|---|---|
| 1 | 5 | - | - |
| 2 | 5 | 10 | - |
| 3 | 15 | 10 | - |
| 4 | 15 | 10 | 5 |
| 5 | 15 | 5 | 5 |
Final values: a is 15, b is 5, c is 5. Line 5 copies the value of c into b; it does not tie them together afterwards.
Why does this fail to swap a and b? Trace it with a = 1 and b = 2. Expected: the values of a and b after the two lines.
a = bb = aShow solution
After a = b, both a and b hold 2, and the original 1 is gone. Then b = a copies 2 into b, which is already 2. The result is a = 2, b = 2. A swap must save one value first (the temporary variable) or use simultaneous assignment.
After this runs, what do x and y contain? Explain why. Expected: the contents of each name.
x = [1, 2]y = xy.append(3)x = [9]Show solution
y is [1, 2, 3] and x is [9]. The append mutates the one shared list, which is why both names would have shown [1, 2, 3] at that point. The last line rebinds x to a brand-new list, which leaves y still pointing at the old one.
Start with a = 1, b = 2, c = 3. Using only assignments and one temporary variable, rotate the values so a holds 2, b holds 3 and c holds 1. Print the three values on one line. Expected output: 2 3 1.
Show solution
Park the first value, then shift each one into the place before it, then put the parked value last.
Python
a = 1b = 2c = 3temp = aa = bb = cc = tempprint(a, b, c)JavaScript
let a = 1;let b = 2;let c = 3;const temp = a;a = b;b = c;c = temp;console.log(a, b, c);Java
public class RotateThree { public static void main(String[] args) { int a = 1; int b = 2; int c = 3; int temp = a; a = b; b = c; c = temp; System.out.println(a + " " + b + " " + c); }}C
#include <stdio.h>
int main(void) { int a = 1; int b = 2; int c = 3; int temp = a; a = b; b = c; c = temp; printf("%d %d %d\n", a, b, c); return 0;}All four print:
2 3 1Summary
- A variable is a name bound to a value;
=stores the result of the right side under the left name. - Reassignment rebinds a name, while mutation changes a shared value; the difference explains many surprising bugs.
- Prefer clear names, follow your language’s conventions, and name fixed values as constants.
Next: Expressions and operators.