Skip to content

Tuples

A tuple is an ordered, immutable sequence.

Tuples are useful when a collection of values should stay fixed after creation. They trade flexibility for safety and predictability.

flowchart TD
    A[tuple]
    A --> B[ordered]
    A --> C[immutable]
    A --> D[hashable when all elements are hashable]

Mental Model

A tuple is a fixed record: once created, its contents cannot change. This immutability makes tuples safe to use as dictionary keys and set elements, and signals to readers that the data is meant to stay constant. Use a tuple when the structure is the point---like coordinates (x, y) or a database row.


1. Creating Tuples

Tuples are usually written with parentheses.

python point = (3, 4) colors = ("red", "green", "blue") empty = ()

A one-element tuple requires a trailing comma.

python single = (5,)

Without the comma, Python interprets (5) as an ordinary grouped expression, not a tuple.


2. Indexing and Slicing

Tuples support indexing and slicing just like other sequences.

```python t = ("a", "b", "c", "d")

print(t[0]) print(t[1:3]) ```

Output:

text a ('b', 'c')

Negative indices count from the end.

python print(t[-1]) print(t[-2])

Output:

text d c

len() returns the number of elements in a tuple.

python print(len(t))

Output:

text 4


3. Immutability

Tuples cannot be changed after creation.

python t = (1, 2, 3) t[0] = 10

Output:

text TypeError: 'tuple' object does not support item assignment

Because tuples are immutable, they can be hashable---but only when all their elements are also hashable. A tuple of integers or strings is hashable; a tuple containing a list is not. Hashable tuples can be used as dictionary keys or set elements, unlike lists. Hashing is covered in more detail in a later chapter.


4. Tuple Packing and Unpacking

Python supports packing multiple values into a tuple and unpacking them into variables.

```python point = 3, 4 x, y = point

print(x) print(y) ```

Output:

text 3 4

Extended unpacking with * collects remaining elements. Note that rest is a list, not a tuple, regardless of the source type.

python first, *rest = (1, 2, 3, 4) print(first) print(rest)

Output:

text 1 [2, 3, 4]


5. When Tuples Are Useful

Tuples are often used for:

  • fixed records such as (name, age) pairs
  • return values from functions
  • dictionary keys (because tuples are hashable)
  • fixed configuration data

6. Worked Examples

Example 1: coordinate pair

python point = (10, 20) print(point[0], point[1])

Output:

text 10 20

Example 2: unpacking

python person = ("Alice", 25) name, age = person print(name, age)

Output:

text Alice 25

Example 3: function returning two values

```python def min_max(a, b): if a < b: return a, b return b, a

print(min_max(8, 3)) ```

Output:

text (3, 8)

Example 4: tuple as dictionary key

```python locations = {} locations[(0, 0)] = "origin" locations[(1, 2)] = "point A"

print(locations[(0, 0)]) ```

Output:

text origin


7. Common Pitfalls

Forgetting the comma in a one-element tuple

python print(type((5))) print(type((5,)))

Output:

text <class 'int'> <class 'tuple'>

Assuming mutable contents cannot change

A tuple itself is immutable, but it may contain mutable elements such as lists. The mutable contents can still be modified in place.

python t = (1, [2, 3]) t[1].append(4) print(t)

Output:

text (1, [2, 3, 4])


8. Summary

Key ideas:

  • tuples are ordered and immutable
  • tuples support indexing, slicing, and negative indexing
  • tuple packing and unpacking are very useful
  • tuples are hashable and can serve as dictionary keys
  • mutable objects inside a tuple can still be changed

Tuples provide a compact and reliable way to represent stable structured data. For a mutable sequence, see Lists.


Notebook Examples

python a = ('1', "2") # tuple b = ('1', "3") c = a + b d = tuple.__add__(a, b) print(c) print(d)

```python a = ( "Hi Bob", "Hi Alice" ) # tuple b = ( "Hi Bob", "Hi Alice" ) # tuple print( a ) # ("Hi Bob", "Hi Alice") print( b ) # ("Hi Bob", "Hi Alice")

a[0] = 0 # TypeError: 'tuple' object does not support item assignment

print( a ) # (0, "Hi Alice")

print( b ) # ("Hi Bob", "Hi Alice")

```

```python a = ( "HI", [1,2,3] ) print(a)

a[1][0] = "One" print(a) ```

```python a = ( "HI", [] ) print(a)

for i in range(1_000): a[1].append(0) print(a) ```

```python a = ( "HI", [] ) id_a = id(a[1])

for i in range(1_000): a[1].append(0) if id_a != id(a[1]): print("WOW") ```

```python

packing and unpacking

a = 25, "Alice" print(a) print(type(a)) ```

```python

packing and unpacking

a, b = 25, "Alice" print(a) print(type(a)) ```

```python

packing and unpacking

a, b = 25, "Alice", "bob" # error print(a) print(type(a)) ```

```python

packing and unpacking

a, b, _ = 25, "Alice", "bob" # ok print(a) print(type(a)) ```

```python

packing and unpacking

a, _, b = 25, "Alice", "bob" # ok print(a) print(type(a)) ```

```python

packing and unpacking

a, _, b = 25, "Alice", "bob", 1, 3, 4, 5 # error print(a) print(type(a)) ```

```python

packing and unpacking

a, *, b = 25, "Alice", "bob", 1, 3, 4, 5 print(a, b, ) ```

```python

packing and unpacking

a, *, b, _ = 25, "Alice", "bob", 1, 3, 4, 5 print(a, b, ) ```

```python

packing and unpacking

def f(): return 25, "Alice", "bob", 1, 3, 4, 5

a, *, b, _ = f() print(a, b, ) ```

```python a = 1 b = 2 print(a, b)

temp_a = a temp_b = b a = temp_b b = temp_a print(a, b) ```

```python a = 1 b = 2 print(a, b)

temp = a a = b b = temp print(a, b) ```

```python a = 1 b = 2 print(a, b)

b, a = a, b print(a, b) ```


Exercises

Exercise 1. A tuple is immutable, yet the following code modifies a tuple's "contents":

python t = (1, [2, 3], 4) t[1].append(5) print(t)

Predict the output. Does this violate tuple immutability? Explain exactly what "immutable" means for a tuple -- what can and cannot change. What would happen if you tried t[1] = [2, 3, 5] instead?

Solution to Exercise 1

Output:

text (1, [2, 3, 5], 4)

This does NOT violate tuple immutability. A tuple's immutability means that the references stored in the tuple cannot be changed -- you cannot make t[0] point to a different object. But the tuple stores a reference to a list object at t[1], and that list object itself is mutable. Modifying the list via t[1].append(5) changes the list object's contents, not the tuple's reference to it.

t[1] = [2, 3, 5] would fail with TypeError: 'tuple' object does not support item assignment, because that tries to change which object t[1] refers to -- which IS a modification of the tuple's structure.

The key insight: immutability of a container means the container's structure (which references it holds) is fixed, but the objects those references point to may themselves be mutable.


Exercise 2. Tuples can be dictionary keys but lists cannot. Explain why immutability is the key property that enables this. Then consider: can a tuple containing a list be used as a dictionary key? Predict what happens and explain why.

Solution to Exercise 2

Dictionary keys must be hashable, which requires that the hash value never changes. Immutable objects can guarantee this because their state never changes, so their hash remains constant.

A tuple containing a list cannot be used as a dictionary key:

python d = {} d[(1, [2, 3])] = "value" # TypeError: unhashable type: 'list'

Even though the tuple itself is immutable, it contains a mutable element (a list), which is unhashable. The tuple's hash would depend on the list's contents, which could change. Python detects this and refuses to compute a hash, raising TypeError.

Only tuples whose every element is also hashable can be used as dictionary keys. A tuple of ints, strings, and other tuples is fine. A tuple containing any mutable element is not.


Exercise 3. Explain the difference between these two lines:

python a = (42) b = (42,)

What are the types of a and b? Why does the comma matter? How would you create a tuple containing a single element?

Solution to Exercise 3

a = (42) -- the parentheses are just grouping (like in math). This is the integer 42. type(a) is int.

b = (42,) -- the trailing comma makes this a one-element tuple. type(b) is tuple.

The comma is what creates a tuple, not the parentheses. In fact, b = 42, (without parentheses) also creates a tuple. The parentheses are optional in most contexts -- they are just used for clarity and for empty tuples (()).

To create a single-element tuple, you must include the trailing comma: (42,) or simply 42,. This syntax exists because Python needed a way to distinguish between "parenthesized expression" and "one-element tuple," and the comma is the disambiguator.