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.
At a Glance
Section titled “At a Glance”| Task | Syntax | Example |
|---|---|---|
| Create | (...), tuple(iterable) | tuple('abc') gives ('a', 'b', 'c') |
| Single item | (x,) | ('Python',) |
| Length | len(t) | len((1, 2, 3)) gives 3 |
| Access | t[i], t[-1] | ('a', 'b')[-1] gives 'b' |
| Slice | t[start:stop:step] | (1, 2, 3, 4)[1:3] gives (2, 3) |
| Combine | +, * | (1,) + (2,) gives (1, 2) |
| Search | x in t, .index(x), .count(x) | 2 in (1, 2, 3) gives True |
| Unpack | a, b, *rest = t | x, y = (10, 20) |
| Sort | sorted(t) | Returns a list |
Creating Tuples
Section titled “Creating Tuples”developer = ('Alice', 34, 'Rust Developer') # Literalchars = tuple('Jessica') # ('J', 'e', 's', 's', 'i', 'c', 'a')empty = () # Empty tuplealso_empty = tuple()
packed = 1, 2, 3 # Parentheses are optionalprint(packed) # (1, 2, 3)The Single-Item Trap
Section titled “The Single-Item Trap”A single-item tuple requires a trailing comma. Without it, the parentheses are just grouping.
single = ('Python',)not_a_tuple = ('Python')
print(type(single)) # <class 'tuple'>print(type(not_a_tuple)) # <class 'str'>Basic Operations
Section titled “Basic Operations”colors = ('red', 'green', 'blue')
print(len(colors)) # 3print(colors[0]) # 'red'print(colors[-1]) # 'blue'print('green' in colors) # Trueprint(colors[3]) # IndexError: tuple index out of range
print(colors + ('pink',)) # ('red', 'green', 'blue', 'pink'), a new tupleprint(('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 itemprint((1, 2) == [1, 2]) # False, a tuple never equals a listSlicing
Section titled “Slicing”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.
| Expression | Result 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) |
Methods
Section titled “Methods”Because tuples cannot change, they have only two methods: count() and index().
.count(value)
Section titled “.count(value)”Returns how many times value appears, or 0 if it does not.
langs = ('Rust', 'Java', 'Python', 'C++', 'Rust')
print(langs.count('Rust')) # 2print(langs.count('JavaScript')) # 0print(langs.count()) # TypeError: tuple.count() takes exactly one argument (0 given).index(value, [start, [stop]])
Section titled “.index(value, [start, [stop]])”Returns the index of the first match. The optional start and stop arguments limit the search window.
langs = ('Rust', 'Java', 'Python', 'C++', 'Rust', 'Python', 'JavaScript', 'Python')
print(langs.index('Java')) # 1print(langs.index('Python', 3)) # 5, search starts at index 3print(langs.index('Python', 2, 5)) # 2, search window is [2, 5)print(langs.index('Go')) # ValueError: tuple.index(x): x not in tupleSorting and Reversing
Section titled “Sorting and Reversing”Tuples have no .sort() or .reverse() methods. Use the built-in functions instead.
| Tool | Returns |
|---|---|
sorted(t) | A new list |
tuple(sorted(t)) | A new sorted tuple |
t[::-1] | A reversed tuple |
reversed(t) | An iterator |
numbers = (13, 2, 78, 3)languages = ('Rust', 'Java', 'Python', 'C++', 'Rust', 'Python')
print(sorted(numbers)) # [2, 3, 13, 78], a listprint(tuple(sorted(numbers))) # (2, 3, 13, 78), back to a tupleprint(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:
records = [(2, 'b'), (1, 'z'), (1, 'a')]print(sorted(records)) # [(1, 'a'), (1, 'z'), (2, 'b')], sorted by first item, then secondUnpacking
Section titled “Unpacking”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.
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, 2a, b = b, a # Swap: a is now 2, b is now 1a, 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)Where Tuples Appear Naturally
Section titled “Where Tuples Appear Naturally”Many Python features produce or consume tuples, and unpacking makes them pleasant to use.
# Returning multiple values from a functiondef min_max(numbers): return min(numbers), max(numbers)
result = min_max([3, 1, 2])print(result) # (1, 3), a single tuplelow, high = min_max([3, 1, 2])
# Looping over pairspairs = [('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 toofor key, value in {'x': 1}.items(): print(key, value) # x 1Immutability
Section titled “Immutability”You cannot assign to, delete, or append to a tuple. These operations fail immediately.
developer = ('Jane Doe', 23, 'Python Developer')
developer[0] = 'JavaScript' # TypeError: 'tuple' object does not support item assignmentdel developer[1] # TypeError: 'tuple' object doesn't support item deletiondeveloper.append('Remote') # AttributeError: 'tuple' object has no attribute 'append'Shallow Immutability
Section titled “Shallow Immutability”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.
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“Changing” a Tuple
Section titled ““Changing” a Tuple”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 tupleBest for simple additions and replacements at the ends.
languages = ('Python', 'Java', 'C++', 'Rust')
temp = list(languages)temp[0] = 'JavaScript'languages = tuple(temp) # ('JavaScript', 'Java', 'C++', 'Rust')Best for several edits, or edits in the middle.
-
Convert the tuple to a list with
list(). -
Modify the list: change, append, insert, or remove items.
-
Freeze the result back into a tuple with
tuple().
Tuples as Dictionary Keys
Section titled “Tuples as Dictionary Keys”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.
locations = { (40.7, -74.0): 'New York', (51.5, -0.1): 'London',}print(locations[(51.5, -0.1)]) # 'London'
hash((1, 2)) # Workshash((1, [2])) # TypeError: unhashable type: 'list'Named Tuples
Section titled “Named Tuples”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.
from typing import NamedTuple
class Point(NamedTuple): x: int y: int
p = Point(3, 4)
print(p.x) # 3, access by nameprint(p[1]) # 4, access by index still worksprint(p) # Point(x=3, y=4)
x, y = p # Unpacking still worksp.x = 10 # AttributeError, named tuple fields are read-onlyTime Complexity
Section titled “Time Complexity”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.
| Operation | Syntax | Complexity |
|---|---|---|
| Length | len(t) | O(1) Fast |
| Index access | t[i] | O(1) Fast |
| Slicing | t[start:stop:step] | O(k) New tuple |
| Concatenation | t1 + t2 | O(n + m) New tuple |
| Membership | x in t | O(n) Scan |
| Count / index | t.count(x), t.index(x) | O(n) Scan |
| Unpacking | a, b, *rest = t | O(n) Assignment |
| Sorting | sorted(t) | O(n log n) Returns a list |
| Item assignment | t[i] = x | Not allowed Forbidden |
Common Mistakes
Section titled “Common Mistakes”| Mistake | Problem | Fix |
|---|---|---|
x = ('Python') | That is a string, not a tuple | x = ('Python',) |
t[0] = 'new' | TypeError, tuples are immutable | Build a new tuple, or use a list |
t.append(x) / t.sort() | AttributeError, no such methods | t + (x,) or sorted(t) |
t + 5 | TypeError, can only join tuples to tuples | t + (5,) |
sorted(t) expecting a tuple | sorted() always returns a list | tuple(sorted(t)) |
| Assuming a tuple is deeply immutable | Nested lists can still change | Use only immutable items inside |
{(1, [2]): 'x'} | TypeError, a list inside makes the tuple unhashable | Use a nested tuple: (1, (2,)) |
a, b = (1, 2, 3) | ValueError, the counts do not match | a, *rest = (1, 2, 3) |
t.index(x) on a missing value | ValueError | Check x in t first |
(1, 2) == [1, 2] expecting True | A tuple never equals a list | Convert one side first |
Best Practices Checklist
Section titled “Best Practices Checklist”- Use tuples for fixed records and lists for collections that change.
- Always write the trailing comma in a single-item tuple.
- Return multiple values from a function as a tuple, and unpack them at the call site.
- Prefer unpacking over indexing, so
name, age = personinstead ofperson[0]andperson[1]. - Use
NamedTuplewhen a tuple has more than two or three fields. - Keep the items inside a tuple immutable if you rely on it being unchangeable or hashable.
- Use tuples as dictionary keys for composite values such as coordinates.
- Remember that
sorted()returns a list, so wrap it intuple()when you need a tuple back.