Skip to Content
Tuples

Tuples

Tuples are ordered, immutable sequences. They can hold mixed types and allow duplicate values.

Creating Tuples

You can build a tuple in several ways:

ApproachExampleUse when
Literal ()row = (2, 4, 6)You know the elements
Empty tupleseq = ()Empty placeholder
tuple()tuple()()Empty tuple (same as ())
tuple(iterable)tuple([2, 4, 6])(2, 4, 6)Convert from list, range, str, set, etc.

A single-element tuple requires a trailing comma: (2,) - without the comma, (2) is just an integer in parentheses.

nums = (2, 4, 6, 8, 10) single = (2,) # tuple not_tuple = (2) # int built = tuple([2, 4, 6]) # (2, 4, 6) empty = () from_list = tuple([2, 4, 6, 8])

Length: Use len(t) to get the number of elements. For tuples this is O(1); the length is stored.

Truthiness: An empty tuple () is falsy; a non-empty tuple is truthy. Use if t: to mean “if the tuple has at least one element” and if not t: for “if the tuple is empty.”

Tuple Methods

MethodDescription
count(x)Return the number of occurrences of x
index(x)Return the index of the first occurrence of x; raises ValueError if missing

Tuples have only these two methods because they are immutable. No append, remove, sort, or reverse.

Access Tuples

Use indexing and slicing the same way as lists. Indices start at 0; negative indices count from the end.

PatternDescriptionExample
t[i]Single element at index inums[2] → 6
t[-1]Last elementnums[-1] → 10
t[i:j]Slice from i to j (excl.)nums[2:5] → (6, 8, 10)
t[:n]First n elementsnums[:4] → (2, 4, 6, 8)
t[n:]From index n to endnums[4:] → (10,)
t[-m:-n]Slice with negative indicesnums[-4:-2] → (4, 6)

Slicing with step: The full form is t[start:stop:step]. step is the stride; omit it and it defaults to 1. Use a negative step to walk backward (e.g. t[::-1] for a reversed copy).

PatternDescriptionExample
t[::k]Every k-th elementnums[::2](2, 6, 10, 14)
t[i::k]Every k-th from index inums[1::2](4, 8, 12, 16)
t[::-1]Reversed (step -1)nums[::-1] → reversed copy

Membership: Use in to check whether an element exists in the tuple.

Value lookup: Use count(x) to count occurrences and index(x) to get the first index. Note: index(x) raises ValueError when the item is not present. Check with x in t first, or wrap in try/except, if you need to handle the missing case.

nums = (2, 4, 6, 8, 10, 12, 14, 16) nums[2] # 6 nums[-1] # 16 nums[2:6] # (6, 8, 10, 12) nums[:4] # (2, 4, 6, 8) nums[4:] # (10, 12, 14, 16) nums[-4:-2] # (12, 14) 4 in nums # True nums.count(6) # 1 nums.index(8) # 3

Reversing a Tuple

Create a new tuple with elements in reverse order. The original tuple is unchanged.

ApproachExampleReturnsMutates original?
tuple(reversed(t))tuple(reversed(nums))New tupleNo
Slice [::-1]nums[::-1]New tupleNo
original = (4, 2, 8, 6, 10) # reversed() returns a reverse iterator; wrap in tuple() to get a tuple nums = tuple(reversed(original)) # nums = (10, 6, 8, 2, 4); original = (4, 2, 8, 6, 10) original = (4, 2, 8, 6, 10) nums = original[::-1] # nums = (10, 6, 8, 2, 4); original = (4, 2, 8, 6, 10)
  • tuple(reversed(t)) - reversed() returns a reverse iterator; wrap in tuple() to get a tuple. O(n) time, O(n) space.
  • t[::-1] - Slice with step -1; creates a new tuple. O(n) time, O(n) space.

Tuples have no reverse() method (unlike lists) because they are immutable.

Unpack Tuples

Assign tuple elements to variables in one statement.

nums = (2, 4, 6) a, b, c = nums # a=2, b=4, c=6

Asterisk *: Collect remaining elements into a list.

nums = (2, 4, 6, 8, 10) first, second, *rest = nums # first=2, second=4, rest=[6, 8, 10] print(type(rest)) # <class 'list'>

Middle unpacking: Use * at any position to capture the rest.

nums = (2, 4, 6, 8, 10) a, *mid, z = nums # a=2, mid=[4, 6, 8], z=10

Mismatched count: The number of variables must match the number of elements, unless * is used to absorb extras.

nums = (2, 4, 6) a, b = nums # ValueError: too many values to unpack a, b, c, d = nums # ValueError: not enough values to unpack a, b, c, *d = (2, 4, 6) # a=2, b=4, c=6, d=[]

Index with loop: Use enumerate(t) when you need both index and value:

row = (2, 4, 6, 8) for i, x in enumerate(row): print(i, x) # 0 2, 1 4, 2 6, 3 8

Update Tuples

Tuples are immutable - you cannot change, add, or remove elements in place. To “update” a tuple, create a new one.

Replace an element: Convert to list, modify, convert back.

nums = (2, 4, 6, 8, 10) temp = list(nums) temp[1] = 0 nums = tuple(temp) # (2, 0, 6, 8, 10)

Add an element: Convert to list, append, convert back - or concatenate with a single-element tuple.

nums = (2, 4, 6, 8, 10) temp = list(nums) temp.append(12) nums = tuple(temp) # (2, 4, 6, 8, 10, 12) print(nums) nums = (2, 4, 6, 8, 10) nums += (12,) # (2, 4, 6, 8, 10, 12)

Remove an element: Convert to list, remove or filter, convert back.

nums = (2, 4, 6, 8, 10) temp = list(nums) temp.remove(6) nums = tuple(temp) # (2, 4, 8, 10)

Join Tuples

Concatenation with +: Both operands must be tuples. Returns a new tuple.

a = (2, 4, 6) b = (8, 10, 12) c = a + b # (2, 4, 6, 8, 10, 12)

Repetition with *: Repeat the tuple a given number of times.

nums = (2, 4, 6) doubled = nums * 2 # (2, 4, 6, 2, 4, 6)

Note: + and * create new tuples; they do not modify the original.

Loop Tuples

Three common patterns: direct iteration, index-based, and while loop.

Direct iteration:

nums = (2, 4, 6, 8) for x in nums: print(x) # 2, 4, 6, 8

Index-based:

nums = (2, 4, 6, 8) for i in range(len(nums)): print(nums[i]) # 2, 4, 6, 8

While loop:

nums = (2, 4, 6, 8) i = 0 while i < len(nums): print(nums[i]) i += 2 # 2, 6 - step by 2

Loop in reverse:

nums = (2, 4, 6, 8) for x in reversed(nums): # O(n) print(x) # 8, 6, 4, 2 for x in nums[::-1]: # O(n) print(x) # 8, 6, 4, 2 - slice with step -1 for i in range(len(nums) - 1, -1, -1): # O(n) print(nums[i]) # 8, 6, 4, 2 - index-based reverse
  • reversed(t) - Returns a reverse iterator; does not create a new tuple.
  • t[::-1] - Slice with step -1; creates a new tuple in reverse order.
  • range(len(t)-1, -1, -1) - Index-based; iterate from last index down to 0.

Why LeetCode often prefers the index-based reverse: When you need to modify elements by index (swap, overwrite, remove), you must have the index. reversed() and t[::-1] give values, not indices. The range(len(t)-1, -1, -1) pattern also avoids index shifting when removing elements in place, and it translates directly to other languages (C, Java, etc.).

Sort Tuples

Tuples have no sort() method because they are immutable. To get a sorted tuple, create a new one using sorted().

sorted(t) returns a list, not a tuple. Wrap in tuple() to get a tuple.

nums = (10, 4, 8, 2, 6) tuple(sorted(nums)) # (2, 4, 6, 8, 10) tuple(sorted(nums, reverse=True)) # (10, 8, 6, 4, 2)

With key: Use key for custom sort order, same as for lists.

nums = (2, 4, 6, 8, 10, 12, 14, 16) tuple(sorted(nums, key=lambda n: abs(n - 10))) # sort by distance from 10 # (10, 8, 12, 6, 14, 4, 16, 2)

Alternative: Convert to list, sort in place, convert back. sorted(t) is simpler and preferred.

nums = (10, 4, 8, 2, 6) temp = list(nums) temp.sort() tuple(temp) # (2, 4, 6, 8, 10)

Tuple vs Other Collections

Python has other built-in types for sequences and collections. Choosing the right one depends on order, mutability, and whether you need hashability.

TypeOrdered?Mutable?Duplicates?Hashable?Typical use
tupleYesNoYesYes (if elements are)Fixed sequences; dict keys; return values
listYesYesYesNoOrdered sequences you change
setNoYesNoN/AUnique items, membership, set math
dictYes (ins.)Yes (vals)No (keys)Keys onlyKey–value mapping

Note: A tuple is hashable only if every element is hashable (e.g. no lists or dicts inside). Lists and sets are not hashable.

Example:

# Hashable tuple (all elements hashable) - valid as dict key key_ok = (2, 4) d = {key_ok: "point"} # {(2, 4): 'point'} # Tuple with a list inside - not hashable key_bad = (2, [4, 6]) # d2 = {key_bad: "x"} # TypeError: unhashable type: 'list' # List cannot be a dict key # d3 = {[2, 4]: "x"} # TypeError: unhashable type: 'list'

When to use a tuple: Fixed sequence (e.g. coordinates, record-like data), dict keys, set elements, or multiple return values from a function. Use a list when you need to append, remove, or reorder. Use a set when you care only about uniqueness or fast membership.

Common use cases:

  • Return values: A function that “returns multiple values” actually returns a tuple. You can unpack it: def min_max(vals): return min(vals), max(vals)lo, hi = min_max([2, 4, 6, 8]) gives lo=2, hi=8.
  • Dict keys and set elements: Tuples are hashable when all elements are hashable, so they can be dict keys or set members. Lists cannot: {(2, 4): "point"} is valid; {[2, 4]: "point"} raises TypeError: unhashable type: 'list'.

Tricky Behaviors

Creating - Single-element tuple

(2) is an int; (2,) is a tuple. The comma is required so Python parses it as a tuple.

Access - index(x) when missing

t.index(x) raises ValueError if x is not in the tuple. Check with x in t first, or use try/except, or something like next((i for i, v in enumerate(t) if v == x), None) for a safe “index or None.”

Update - Immutability and nested mutables

The tuple itself cannot be changed, but if an element is mutable (e.g. a list), that object’s contents can change. t = (1, [2, 4]); t[1].append(6) is allowed and makes t equal to (1, [2, 4, 6]).

Join - t + other with non-tuple

Concatenation requires both sides to be tuples. (2, 4) + [6, 8] raises TypeError. Use (2, 4) + tuple([6, 8]) or convert the other iterable to a tuple first.

Sort - sorted(t) returns a list

sorted(t) gives a list, not a tuple. Use tuple(sorted(t)) when you need a sorted tuple. Forgetting the wrapper is a common mistake when coming from other languages or when you assume sorted() returns the same type.

Assignment is not copy

b = a makes b refer to the same tuple as a. Since tuples are immutable, this rarely causes surprises, but if you need a new tuple from an existing one you can use t[:] or tuple(t) - both produce a shallow copy (same elements, same tuple type).

Interview Questions

How do you create a single-element tuple?

Use a trailing comma: (2,). Without the comma, (2) is just an integer in parentheses.

Why does a tuple have only count and index?

Tuples are immutable, so they have no mutating methods. count and index are the only read-only operations needed; no append, remove, sort, or reverse.

How do you reverse a tuple?

Use tuple(reversed(t)) or t[::-1]. Both create a new tuple in reverse order; the original is unchanged. Tuples have no reverse() method (unlike lists) because they are immutable.

What does * do in tuple unpacking?

Collects remaining elements into a list: first, *rest = numsrest = [4, 6, 8, 10]. Use at any position: a, *mid, z = nums.

Can you “modify” a tuple? How?

Tuples are immutable. To change, add, or remove elements, convert to list, modify, convert back: tuple(list(t)) or use + for concatenation.

How do you sort a tuple?

tuple(sorted(t)) - sorted() returns a list, so wrap in tuple(). Use key for custom order: tuple(sorted(t, key=fn)).

Why use a tuple instead of a list?

Immutability (safe as dict key, set element); slightly less memory; semantic “fixed structure.” Tuples are hashable if all elements are hashable.

When can a tuple be a dict key? Why can’t a list?

A tuple can be a dict key only if every element is hashable (e.g. ints, strings, other tuples of hashable types). Then the tuple is hashable and can be used as a key. A list is mutable and unhashable, so {[2, 4]: "x"} raises TypeError: unhashable type: 'list'. Use a tuple when you need a sequence as a key: {(2, 4): "point"} works.

What does return a, b return from a function?

A tuple (a, b). The comma makes it a tuple. Callers can unpack: x, y = f() or use as a single value: result = f()result is (a, b).

Last updated on