Tuples: Lists That Can't Be Changed
1 · The lesson
readA tuple is an ordered sequence, like a list. It has the same indexing (t[0]), the same slicing (t[1:3]) and the same iteration (for x in t:). But once you create a tuple, it can never be modified: you can't add, remove or replace its items.
That sounds like a limitation, and sometimes it is. But it is also the reason a tuple can be a dictionary key. Tuples are also how a function returns several values at once. You will use both of these all the time.
1. Creating Tuples
You create a tuple with parentheses instead of square brackets:
# A tuple of coordinates point = (3, 4) print(point) # (3, 4) print(type(point)) # <class 'tuple'> # Multiple types are fine, same as lists person = ("Alice", 30, True) print(person) # ('Alice', 30, True) # An empty tuple empty = () print(len(empty)) # 0 # A tuple with one element MUST have a comma not_a_tuple = (42) # this is just an int in parentheses real_tuple = (42,) # this is a tuple print(type(not_a_tuple)) # <class 'int'> print(type(real_tuple)) # <class 'tuple'>
That trailing comma for single-element tuples is the most common tuple gotcha. Remember it.
You can even leave the parentheses out. It's the commas that make a tuple:
point = 3, 4 # also a tuple print(point) # (3, 4) print(type(point)) # <class 'tuple'>
2. Reading from Tuples (Same as Lists)
Indexing, slicing and len() work exactly as they do on lists:
person = ("Alice", 30, "Engineer") print(person[0]) # Alice print(person[-1]) # Engineer print(person[0:2]) # ('Alice', 30) print(len(person)) # 3 # Iteration works too for item in person: print(item)
3. What You CAN'T Do
Tuples are immutable. Anything that would change a list in place raises an error on a tuple:
point = (3, 4) # All of these would crash: # point[0] = 5 # TypeError: 'tuple' object does not support item assignment # point.append(7) # AttributeError: 'tuple' object has no attribute 'append' # del point[0] # TypeError: 'tuple' object doesn't support item deletion # What you CAN do: create a new tuple new_point = point + (5,) print(new_point) # (3, 4, 5) # Or rebuild from scratch updated = (point[0], 99) print(updated) # (3, 99)
+ creates a new tuple, and the original tuple does not change. * (repetition) also creates a new tuple.
4. Why Tuples Exist: When to Use Them
Three real reasons to reach for a tuple instead of a list:
a) The data should never change. Nobody should append a third number to the coordinate (3, 4), or edit the date (2026, 5, 14) in place. A tuple tells the next person who reads your code: these values are one unit, do not change them.
b) You want to use it as a dictionary key. A list can't be a dict key, because a list can change, and then its hash would change too. A tuple can be a key:
# Mapping a 2D grid coordinate to a value board = {} board[(0, 0)] = "X" board[(1, 2)] = "O" print(board) # {(0, 0): 'X', (1, 2): 'O'}
c) A function returning several values. In real code, this is the reason you will see most often:
def get_user(): # Returning "multiple values" actually means returning a tuple return "Alice", 30, "alice@example.com" name, age, email = get_user() print(name) # Alice print(age) # 30 print(email) # alice@example.com
The line name, age, email = get_user() is called tuple unpacking. You will write lines like it all the time.
5. Tuple Unpacking
You can assign multiple variables from a single tuple in one line:
# Basic unpacking point = (3, 4) x, y = point print(x, y) # 3 4 # Works in for-loops too pairs = [(1, "one"), (2, "two"), (3, "three")] for number, word in pairs: print(f"{number} is {word}") # Swap two variables, with no temporary variable needed! a = 10 b = 20 a, b = b, a # this works by tuple unpacking print(a, b) # 20 10 # Star unpacking: collect "the rest" into a list first, *middle, last = (1, 2, 3, 4, 5) print(first) # 1 print(middle) # [2, 3, 4] print(last) # 5
In C or Java, swapping two variables takes three lines and a temporary variable. In Python, a, b = b, a does it in one.
6. Tuples vs Lists: Quick Reference
| Feature | List [1, 2, 3] | Tuple (1, 2, 3) |
|---|---|---|
| Mutable? | Yes (can change) | No (frozen) |
| Syntax | Square brackets | Parentheses (or commas) |
| Can be dict key | No | Yes |
| Slightly faster? | No | Yes (small win) |
| Common use | Collections that grow/shrink | Fixed records, multi-return, coordinates |
| Methods | Many (append, pop, sort, …) | Just two (count, index) |
Rule of thumb: if the collection will grow, shrink or change, use a list. If the values belong together as one record, use a tuple.
7. Mistakes You'll Hit
1. Forgetting the comma on a single-element tuple
x = (5) # this is just the integer 5 x = (5,) # this is a tuple with one element
2. Trying to modify a tuple
# t = (1, 2, 3) # t[0] = 99 # TypeError: tuples are immutable
Fix: create a new tuple, or use a list if you need to mutate.
3. A comma you didn't mean makes a tuple
a = 1, 2, 3 # tuple: a = (1, 2, 3) b = [1, 2, 3] # list
🎯 Your Turn: Return Three Things at Once
A function can only return one object, but that object can be a tuple. That's how
Python functions return several values at once without inventing a class.
Write summarise(numbers) that returns a tuple of (smallest, largest, average),
then unpack it at the call site into three named variables.
summarise([4, 8, 15, 16, 23, 42]) → (4, 42, 18.0) summarise([7]) → (7, 7, 7.0) summarise([-5, 5]) → (-5, 5, 0.0)
Return None for an empty list rather than crashing.
This exercise uses def, which you will learn in the next lesson, Functions & Scoping. For now, copy the skeleton as it is and fill in the lines marked TODO.
Skeleton:
def summarise(numbers): # TODO 1: return None if the list is empty # TODO 2: build the tuple (min, max, average), with the average as a float ... low, high, mean = summarise([4, 8, 15, 16, 23, 42]) print(f"low={low} high={high} mean={mean}") # low=4 high=42 mean=18.0 print(summarise([])) # None
Hint 1: The parentheses are optional
return smallest, largest, average already builds a tuple. The commas
are what make it one, not the brackets. Writing return (a, b, c) is
the same thing and is often clearer to read.
Hint 2: Unpacking must match in length
low, high, mean = summarise(...) works because the tuple has exactly
three items. If it had four you would get ValueError: too many values to
unpack. This is useful: Python reports the mistake on that line, instead of
passing a wrong value on to the rest of your program.
Show full solution
def summarise(numbers): if not numbers: return None return min(numbers), max(numbers), sum(numbers) / len(numbers) low, high, mean = summarise([4, 8, 15, 16, 23, 42]) print(f"low={low} high={high} mean={mean}") # low=4 high=42 mean=18.0 print(summarise([7])) # (7, 7, 7.0) print(summarise([-5, 5])) # (-5, 5, 0.0) print(summarise([])) # None
The tuple does the job a small class would do in other languages: it groups three
values that belong together. Because it's immutable, the caller can't change the
result by accident and confuse later code. Python's own divmod() andstr.partition() return tuples for the same reason, and looping overdict.items() hands you one (key, value) tuple at a time.
What You Learned
- Tuples are immutable ordered sequences: you read them with the same syntax as lists, but you can't add, remove or replace items.
- Create with parentheses or just commas:
(3, 4)or3, 4. - A one-element tuple needs a trailing comma:
(42,). - Use tuples for fixed records, dict keys, and multi-return values.
- Tuple unpacking assigns several variables in one line, and swaps two without a temporary variable.
You will create fewer tuples than lists, but you will use them more often than you might think: every function that returns more than one value is returning a tuple.
Next: Functions & Scoping.
Source: adapted from Python official documentation Section 5.3 (Tuples and Sequences). PSF License.
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code did, as well as whether a test passed.
Found this useful? Share it with a friend who’s learning Python.