Skip to content

Python Tuples

A tuple (tuple) Immutable is an ordered collection that cannot be changed after it is created. Tuples are ideal for fixed records, multiple return values, and dictionary keys.

TaskSyntaxExample
Create(...), tuple(iterable)tuple('abc') gives ('a', 'b', 'c')
Single item(x,)('Python',)
Lengthlen(t)len((1, 2, 3)) gives 3
Accesst[i], t[-1]('a', 'b')[-1] gives 'b'
Slicet[start:stop:step](1, 2, 3, 4)[1:3] gives (2, 3)
Combine+, *(1,) + (2,) gives (1, 2)
Searchx in t, .index(x), .count(x)2 in (1, 2, 3) gives True
Unpacka, b, *rest = tx, y = (10, 20)
Sortsorted(t)Returns a list
creating_tuples.py
developer = ('Alice', 34, 'Rust Developer') # Literal
chars = tuple('Jessica') # ('J', 'e', 's', 's', 'i', 'c', 'a')
empty = () # Empty tuple
also_empty = tuple()
packed = 1, 2, 3 # Parentheses are optional
print(packed) # (1, 2, 3)

A single-item tuple requires a trailing comma. Without it, the parentheses are just grouping.

single_item_tuple.py
single = ('Python',)
not_a_tuple = ('Python')
print(type(single)) # <class 'tuple'>
print(type(not_a_tuple)) # <class 'str'>

basic_operations.py
colors = ('red', 'green', 'blue')
print(len(colors)) # 3
print(colors[0]) # 'red'
print(colors[-1]) # 'blue'
print('green' in colors) # True
print(colors[3]) # IndexError: tuple index out of range
print(colors + ('pink',)) # ('red', 'green', 'blue', 'pink'), a new tuple
print(('ab',) * 2) # ('ab', 'ab')
nums = (3, 1, 2)
print(min(nums), max(nums), sum(nums)) # 1 3 6
print((1, 2) < (1, 3)) # True, compared item by item
print((1, 2) == [1, 2]) # False, a tuple never equals a list

Slicing uses the same [start:stop:step] rules as lists and strings: stop is excluded, omitted bounds use the defaults, and a negative step walks backward. Slicing returns a new tuple.

ExpressionResult for nums = (10, 20, 30, 40, 50)
nums[1:4](20, 30, 40)
nums[:2](10, 20)
nums[3:](40, 50)
nums[-2:](40, 50)
nums[::2](10, 30, 50)
nums[::-1](50, 40, 30, 20, 10)
nums[10:]() (out-of-range slices never raise errors)

Because tuples cannot change, they have only two methods: count() and index().

Returns how many times value appears, or 0 if it does not.

tuple_count.py
langs = ('Rust', 'Java', 'Python', 'C++', 'Rust')
print(langs.count('Rust')) # 2
print(langs.count('JavaScript')) # 0
print(langs.count()) # TypeError: tuple.count() takes exactly one argument (0 given)

Returns the index of the first match. The optional start and stop arguments limit the search window.

tuple_index.py
langs = ('Rust', 'Java', 'Python', 'C++', 'Rust', 'Python', 'JavaScript', 'Python')
print(langs.index('Java')) # 1
print(langs.index('Python', 3)) # 5, search starts at index 3
print(langs.index('Python', 2, 5)) # 2, search window is [2, 5)
print(langs.index('Go')) # ValueError: tuple.index(x): x not in tuple

Tuples have no .sort() or .reverse() methods. Use the built-in functions instead.

ToolReturns
sorted(t)A new list
tuple(sorted(t))A new sorted tuple
t[::-1]A reversed tuple
reversed(t)An iterator
tuple_sorting.py
numbers = (13, 2, 78, 3)
languages = ('Rust', 'Java', 'Python', 'C++', 'Rust', 'Python')
print(sorted(numbers)) # [2, 3, 13, 78], a list
print(tuple(sorted(numbers))) # (2, 3, 13, 78), back to a tuple
print(sorted(languages, key=len)) # ['C++', 'Rust', 'Java', 'Rust', 'Python', 'Python']
print(sorted(languages, reverse=True)) # ['Rust', 'Rust', 'Python', 'Python', 'Java', 'C++']

Tuples of tuples sort item by item, which makes them handy for multi-level sorting:

sorting_tuples_of_tuples.py
records = [(2, 'b'), (1, 'z'), (1, 'a')]
print(sorted(records)) # [(1, 'a'), (1, 'z'), (2, 'b')], sorted by first item, then second

Unpacking assigns each item of a tuple to its own variable. The number of variables must match the number of items, unless you use a starred name to collect the extras.

unpacking.py
developer = ('Alice', 34, 'Rust Developer', 'Gauteng', 'South Africa')
name, age, job, region, country = developer # Exact unpacking
name, *rest = developer
# name -> 'Alice'
# rest -> [34, 'Rust Developer', 'Gauteng', 'South Africa'] (always a list)
first, *middle, last = (1, 2, 3, 4, 5) # 1, [2, 3, 4], 5
name, age, *_ = developer # _ is a convention for "ignore this"
person = ('Alice', (34, 'Gauteng'))
name, (age, region) = person # Nested unpacking
a, b = 1, 2
a, b = b, a # Swap: a is now 2, b is now 1
unpacking_errors.py
a, b = (1, 2, 3) # ValueError: too many values to unpack (expected 2)
a, b, c = (1, 2) # ValueError: not enough values to unpack (expected 3, got 2)

Many Python features produce or consume tuples, and unpacking makes them pleasant to use.

tuples_in_the_wild.py
# Returning multiple values from a function
def min_max(numbers):
return min(numbers), max(numbers)
result = min_max([3, 1, 2])
print(result) # (1, 3), a single tuple
low, high = min_max([3, 1, 2])
# Looping over pairs
pairs = [('Ann', 31), ('Bob', 25)]
for name, age in pairs:
print(name, age)
for index, value in enumerate(('a', 'b')):
print(index, value) # 0 a, 1 b
# Dictionary items are tuples too
for key, value in {'x': 1}.items():
print(key, value) # x 1

You cannot assign to, delete, or append to a tuple. These operations fail immediately.

immutability.py
developer = ('Jane Doe', 23, 'Python Developer')
developer[0] = 'JavaScript' # TypeError: 'tuple' object does not support item assignment
del developer[1] # TypeError: 'tuple' object doesn't support item deletion
developer.append('Remote') # AttributeError: 'tuple' object has no attribute 'append'

Immutability covers only the tuple’s own references. If a tuple contains a mutable object such as a list, that object can still be changed.

shallow_immutability.py
container = (1, 2, ['Python', 'C++'])
container[2].append('Rust')
print(container) # (1, 2, ['Python', 'C++', 'Rust']), the list changed
container[2] = ['Other'] # TypeError, the reference itself is fixed

To get an updated version, build a new tuple and rebind the name.

languages = ('Python', 'Java', 'C++', 'Rust')
replaced = ('JavaScript',) + languages[1:] # ('JavaScript', 'Java', 'C++', 'Rust')
appended = languages + ('Go',) # ('Python', 'Java', 'C++', 'Rust', 'Go')
languages += ('Go',) # Rebinds the name to a new tuple

Best for simple additions and replacements at the ends.

  1. Convert the tuple to a list with list().

  2. Modify the list: change, append, insert, or remove items.

  3. Freeze the result back into a tuple with tuple().


Tuples are hashable as long as every item inside them is hashable, so they can be used as dictionary keys and set members. Lists cannot.

tuple_keys.py
locations = {
(40.7, -74.0): 'New York',
(51.5, -0.1): 'London',
}
print(locations[(51.5, -0.1)]) # 'London'
hash((1, 2)) # Works
hash((1, [2])) # TypeError: unhashable type: 'list'

When a tuple has many fields, positions like t[2] become hard to read. A named tuple lets you access items by name while remaining a real, immutable tuple.

named_tuples.py
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
p = Point(3, 4)
print(p.x) # 3, access by name
print(p[1]) # 4, access by index still works
print(p) # Point(x=3, y=4)
x, y = p # Unpacking still works
p.x = 10 # AttributeError, named tuple fields are read-only

Big-O notation describes how an operation’s cost grows with the tuple size n. O(1) means constant time, O(n) means the cost grows with the number of items, and O(k) means it depends on the number of items k being copied.

OperationSyntaxComplexity
Lengthlen(t)O(1) Fast
Index accesst[i]O(1) Fast
Slicingt[start:stop:step]O(k) New tuple
Concatenationt1 + t2O(n + m) New tuple
Membershipx in tO(n) Scan
Count / indext.count(x), t.index(x)O(n) Scan
Unpackinga, b, *rest = tO(n) Assignment
Sortingsorted(t)O(n log n) Returns a list
Item assignmentt[i] = xNot allowed Forbidden

MistakeProblemFix
x = ('Python')That is a string, not a tuplex = ('Python',)
t[0] = 'new'TypeError, tuples are immutableBuild a new tuple, or use a list
t.append(x) / t.sort()AttributeError, no such methodst + (x,) or sorted(t)
t + 5TypeError, can only join tuples to tuplest + (5,)
sorted(t) expecting a tuplesorted() always returns a listtuple(sorted(t))
Assuming a tuple is deeply immutableNested lists can still changeUse only immutable items inside
{(1, [2]): 'x'}TypeError, a list inside makes the tuple unhashableUse a nested tuple: (1, (2,))
a, b = (1, 2, 3)ValueError, the counts do not matcha, *rest = (1, 2, 3)
t.index(x) on a missing valueValueErrorCheck x in t first
(1, 2) == [1, 2] expecting TrueA tuple never equals a listConvert one side first
  1. Use tuples for fixed records and lists for collections that change.
  2. Always write the trailing comma in a single-item tuple.
  3. Return multiple values from a function as a tuple, and unpack them at the call site.
  4. Prefer unpacking over indexing, so name, age = person instead of person[0] and person[1].
  5. Use NamedTuple when a tuple has more than two or three fields.
  6. Keep the items inside a tuple immutable if you rely on it being unchangeable or hashable.
  7. Use tuples as dictionary keys for composite values such as coordinates.
  8. Remember that sorted() returns a list, so wrap it in tuple() when you need a tuple back.