Tuples, Immutability, and Packing

Key Takeaways

  • Tuples are ordered sequences, so they support indexing, slicing, len, iteration, and membership tests.
  • Tuples are immutable, so assigning to an element or deleting one element raises TypeError.
  • A one-item tuple requires a trailing comma, such as (value,), because parentheses alone do not create a tuple.
  • Tuple packing and unpacking let Python group several values and assign them back to names position by position.
  • A tuple is hashable only when all of its elements are hashable, which matters when using tuples as dictionary keys.
Last updated: June 2026

Tuple basics

A tuple is an ordered sequence, usually written with parentheses. Like a list or string, it supports indexing, negative indexing, slicing, len(), membership with in, and iteration in a for loop. The major difference is immutability: after a tuple is created, its element positions cannot be reassigned, inserted into, or removed from individually.

point = (10, 20, 30)
print(point[0])     # 10
print(point[-1])    # 30
print(point[1:3])   # (20, 30)
print(len(point))   # 3
print(20 in point)  # True

Trying to change a tuple element raises TypeError.

point = (10, 20)
point[0] = 99       # TypeError

This does not mean the variable name is frozen. You can rebind the name to a different tuple; the original tuple object is what cannot change.

point = (10, 20)
point = (99, 20)    # allowed: name now refers to a new tuple

The comma creates the tuple

A common PCEP trap is the one-item tuple. Parentheses are often used merely to group expressions, so (5) is just the integer 5. The trailing comma is what actually makes a tuple.

ExpressionResulting typeNote
(5)intParentheses only group the expression
(5,)tupleOne-item tuple
5,tupleOne-item tuple without parentheses
(5, 6)tupleTwo-item tuple
()tupleThe empty tuple
5intPlain integer

When reading code, look for the comma before assuming a value is a tuple. A snippet like x = (3) * 2 produces 6, but x = (3,) * 2 produces (3, 3).

Packing and unpacking

Packing happens when Python gathers values into a tuple. Unpacking assigns elements from a tuple or other iterable into separate names.

record = 'Ada', 36, 'Python'   # packing (no parentheses needed)
name, age, language = record   # unpacking
print(name)                    # Ada

The number of target names must match the number of values unless starred unpacking is used. PCEP usually tests the simple rule: two names need exactly two values, three names need exactly three values, or Python raises ValueError.

x, y = (1, 2)       # works
x, y = (1, 2, 3)    # ValueError: too many values to unpack

Swapping and starred unpacking

A useful unpacking pattern swaps values without a temporary variable. Python evaluates the right side first, packs those values into a tuple, then unpacks them into the left-side names.

left, right = 'L', 'R'
left, right = right, left
print(left, right)   # R L

Starred unpacking collects extra values into a list:

first, *rest = (1, 2, 3, 4)
print(first)  # 1
print(rest)   # [2, 3, 4]  (a list, not a tuple)

Immutable tuple, mutable contents

Tuple immutability applies to the tuple positions, not necessarily to the objects inside them. A tuple can contain a list: you cannot replace the list at that tuple position, but you can mutate the list itself.

box = ([1, 2], 'ok')
box[0].append(3)
print(box)  # ([1, 2, 3], 'ok')

That distinction matters for dictionary keys and set elements. A tuple is hashable only if every element inside it is hashable. (1, 2) can be a dictionary key; ([1, 2], 3) cannot, because the list inside it is mutable and unhashable.

Tuple methods and use cases

Tuples have far fewer methods than lists; the only two are count(value) and index(value) (both reads, since there is nothing to mutate). Use tuples when the structure should be fixed: a coordinate, a small record, dictionary keys, or multiple values returned from a function. Use lists when the collection is meant to grow, shrink, or be reordered. Because tuples cannot change size, they are slightly faster and signal intent that the data is constant.

Conversions, concatenation, and exam traps

The PCEP exam often blends tuples with the other collection types, so know how they convert and combine. The tuple() constructor turns any iterable into a tuple, so tuple([1, 2, 3]) gives (1, 2, 3) and tuple('hi') gives ('h', 'i'); conversely list((1, 2)) gives [1, 2]. Tuples support + and * like other sequences: (1, 2) + (3,) yields (1, 2, 3) and (0,) * 3 yields (0, 0, 0), but you still cannot concatenate a tuple with a list.

A subtle augmented-assignment trap appears when a tuple holds a mutable element: writing t = ([1], 2); t[0] += [9] actually mutates the inner list to [1, 9] and then raises TypeError because the tuple rejects the rebinding — yet the list change has already happened, so the inner list ends up [1, 9] despite the error. Functions commonly return tuples implicitly: return a, b packs the two values into a tuple, and the caller can unpack with x, y = func(). Because membership and comparison work element by element, (1, 2) == (1, 2) is True and (1, 2) < (1, 3) is True.

When a question shows parentheses, slow down and decide first whether a comma is present, because that single character changes an integer into a tuple and changes the entire predicted output of the snippet.

Test Your Knowledge

Which expression creates a tuple containing exactly one integer?

A
B
C
D
Test Your Knowledge

What happens when this code runs? t = (1, 2); t[0] = 9

A
B
C
D
Test Your Knowledge

Which value can be used as a dictionary key because it is hashable?

A
B
C
D