Tuples#

A tuple is similar to a list in that it stores multiple ordered elements, but it cannot be modified after creation (immutable):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Create a tuple
t1 = (1, 2, 3)
t2 = ("apple", "banana", "cherry")
t3 = (1, "hello", 3.14, True)  # Mixed types are allowed

# Single-element tuple: must include a comma!
single = (42,)
print(type(single))   # <class 'tuple'>

# Without comma it's just parentheses, not a tuple
not_tuple = (42)
print(type(not_tuple))  # <class 'int'>

# Can also omit parentheses
t4 = 1, 2, 3
print(type(t4))  # <class 'tuple'>

Accessing and Querying#

Tuples support most non-mutating list operations:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
t = (10, 20, 30, 40, 50)

# Indexing and slicing
print(t[0])      # 10
print(t[-1])     # 50
print(t[1:4])    # (20, 30, 40)

# Querying
print(30 in t)        # True
print(t.count(20))    # 1
print(t.index(30))    # 2
print(len(t))         # 5

# Iteration
for item in t:
    print(item)

Unpacking#

One of the most useful features of tuples is the ability to unpack them directly into multiple variables:

1
2
3
4
t = (10, 20, 30, 40, 50)

a, b, c, d, e = t
print(a, b, c)  # 10 20 30

Star unpacking#

1
2
3
4
5
6
7
8
9
# Remaining elements collected into list
first, *rest = (1, 2, 3, 4, 5)
print(first)  # 1
print(rest)   # [2, 3, 4, 5]

first, *middle, last = (1, 2, 3, 4, 5)
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

Swap two variables#

Using tuple unpacking, you can swap without a temporary variable:

1
2
3
x, y = 10, 20
x, y = y, x
print(x, y)  # 20 10

Tuples vs Lists#

FeatureTuple tupleList list
MutableNo (immutable)Yes (mutable)
Syntax(1, 2, 3)[1, 2, 3]
Can be used as dict keyYesNo
Memory usageLessMore
Best forFixed data, multiple return valuesDynamically growing data

When to Use Tuples?#

Fixed/immutable data#

1
2
3
# Coordinates, RGB colors — data that semantically shouldn't change
position = (25.0, 121.5)   # latitude, longitude
color = (255, 128, 0)      # RGB values

Returning multiple values from a function#

When a function returns multiple values, it’s actually returning a tuple:

1
2
3
4
5
6
7
8
9
def min_max(numbers):
    return min(numbers), max(numbers)

lo, hi = min_max([3, 1, 4, 1, 5, 9])
print(lo, hi)  # 1 9

# Confirm return type
result = min_max([3, 1, 4])
print(type(result))  # <class 'tuple'>

As dictionary keys#

Because tuples are immutable, they are hashable and can be used as dict keys; lists cannot:

1
2
3
4
5
6
7
8
locations = {
    (25.0478, 121.5319): "Taipei Station",
    (22.6273, 120.3014): "Kaohsiung Station",
}
print(locations[(25.0478, 121.5319)])  # Taipei Station

# The following raises an error
# bad = {[1, 2]: "value"}  # ❌ TypeError: unhashable type: 'list'

Memory efficiency#

Tuples use less memory than lists and iterate slightly faster:

1
2
3
4
5
6
7
import sys

lst = [1, 2, 3, 4, 5]
tup = (1, 2, 3, 4, 5)

print(sys.getsizeof(lst))  # 88 (bytes, more)
print(sys.getsizeof(tup))  # 72 (bytes, less)

Common Techniques#

Convert between tuple and list#

1
2
3
4
5
t = (1, 2, 3)
lst = list(t)   # Convert to list (mutable)
lst.append(4)
t2 = tuple(lst)  # Convert back to tuple
print(t2)  # (1, 2, 3, 4)

Creating list of tuples with zip()#

1
2
3
4
5
6
7
8
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]

pairs = list(zip(names, scores))
print(pairs)  # [('Alice', 85), ('Bob', 92), ('Charlie', 78)]

for name, score in pairs:
    print(f"{name}: {score} points")

Named tuple (namedtuple)#

When a tuple has many fields, namedtuple makes code more readable:

1
2
3
4
5
6
7
8
from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)

print(p.x, p.y)    # 3 4 (accessible by name)
print(p[0], p[1])  # 3 4 (also accessible by index)
print(p)           # Point(x=3, y=4)